<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>FreiK's WebLog : Developer Info</title><link>http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx</link><description>Tags: Developer Info</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>How to use RtlUnwindEx</title><link>http://blogs.msdn.com/freik/archive/2007/03/15/how-to-use-rtlunwindex.aspx</link><pubDate>Thu, 15 Mar 2007 18:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1887999</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/freik/comments/1887999.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=1887999</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=1887999</wfw:comment><description>&lt;P&gt;Disclaimer:&amp;nbsp; I've never actually written an unwind personality routine, so take what's here with a grain of salt.&lt;/P&gt;
&lt;P&gt;A few days back, I spent 30 minutes defending the C++ runtime's exception handling personality routine to the guy that has the less than enviable job of supporting the .Net Framework's exception handling personality routine.&amp;nbsp; The eventual point to be learned is that the documentation for RtlUnwindEx is abysmal, and can cause the VC 8.0 C++ runtime to leak objects left and right.&lt;/P&gt;
&lt;P&gt;The problem revolves around the C++ team's decision (which I fully support) to cause code compiled with /EHs or /EHsc flags to only invoke destructors when a C++ exception occurs.&amp;nbsp; This means that if you take a hardware exception, call RaiseException yourself, or call&amp;nbsp;longjmp&amp;nbsp;none of your C++ destructors between the point of exception and the handler will be invoked. I've talked about why this is a good idea, but I'll sum it up with this:&amp;nbsp; If that scenario seems bad to you, then you should be compiling your code with /EHa.&lt;/P&gt;
&lt;P&gt;Anyway, back to the issue:&amp;nbsp; Say I'm writing a 'personality routine' which will be inovked by the OS when an exception occurs.&amp;nbsp; If you're writing the kind that requires that your handler initiates the second phase of unwind, you need to call RtlUnwindEx.&amp;nbsp; The documentation, which is arguably&amp;nbsp;bad (it's little more that a function declaration), indicates that the EXCEPTION_RECORD structure to pass in is &lt;EM&gt;optional&lt;/EM&gt;.&amp;nbsp; And that's true:&amp;nbsp; the functions on the stack will still be unwound.&amp;nbsp; But the personality routines for those functions might want to actually know that they're being invoked due to an exception, and not for something like a longjmp.&amp;nbsp; So, if you have an exception record that &lt;EM&gt;could &lt;/EM&gt;be passed to the RtlUnwindEx function, you &lt;EM&gt;should&lt;/EM&gt;.&amp;nbsp; If you don't, another personality routine might assume that there's not an exception to examine, and might decide to do something like NOT invoke the destructors for the object on the stack.&lt;/P&gt;
&lt;P&gt;BTW - this bug exists only on x86, and only when you're crossing a managed code -&amp;gt; native code boundary, in particularly weird scenarios.&amp;nbsp; And I hope it's getting fixed :-)&lt;/P&gt;
&lt;P mce_keep="true"&gt;-Kev&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1887999" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category><category domain="http://blogs.msdn.com/freik/archive/tags/Bugs/default.aspx">Bugs</category></item><item><title>AMD64 unwind info gotchas</title><link>http://blogs.msdn.com/freik/archive/2007/03/12/amd64-unwind-info-gotchas.aspx</link><pubDate>Mon, 12 Mar 2007 20:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1866832</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/freik/comments/1866832.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=1866832</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=1866832</wfw:comment><description>&lt;P&gt;I had a brief e-mail&amp;nbsp;exchange with one of the devs on&amp;nbsp;the optimizer team about a checkin he put up for review.&amp;nbsp; He modified the compiler so that it only aligns the stack for functions that call other functions - that's the typical definition in compiler lingo of a 'leaf function'.&amp;nbsp; My first response was "don't do that - you may still have to align for reasons A, B, &amp;amp; C".&amp;nbsp; To which he responded with a quote from the ABI doc that explicitly says you only have to align the stack if you're calling a function.&amp;nbsp; So I started reading.&amp;nbsp; Turns out, he's right (and so is the doc), but there are some really nasty gotchas involved.&amp;nbsp; When we initially did this stuff, we just lived with the scenario where you might be wasting a bit more stack space...&lt;/P&gt;
&lt;P&gt;The theme of the problems revolve around restrictions on encoding information in the unwind data. If you are saving XMM registers and have an unaligned stack pointer, you must use the SAVE_XMM128_FAR opcode because the SAVE_XMM128 opcode will only accept offsets in multiples of 16 bytes.&amp;nbsp; Or I guess you could use MOVUPS instead of MOVAPS to save &amp;amp; restore your XMM register, but I wouldn't recommend that on current hardware. Similarly, you have to use the ALLOC_LARGE descriptor for stack allocation of sizes that aren’t [n *&amp;nbsp;8 + 8].&amp;nbsp;ALLOC_LARGE actually has 2 variants - one that multiples by 8, and the other than doesn't.&amp;nbsp; You can use the latter to allocate random amounts of data from the stack.&amp;nbsp; But then if you want to use a frame pointer, you're going to be in a pretty weird spot, because it will have to be unaligned, as well. Unwind data dictates that you can only have a frame pointer that = RSP + 16 * [1-15].&lt;/P&gt;
&lt;P&gt;I'll probably come back to this article &amp;amp; add some nice hyperlinks to ABI details in the doc itself, but it's been a while since I blogged anything useful, so I figured I'd just get this out there quickly.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1866832" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category><category domain="http://blogs.msdn.com/freik/archive/tags/X64+ABI+Info/default.aspx">X64 ABI Info</category></item><item><title>New Job, SP1</title><link>http://blogs.msdn.com/freik/archive/2006/12/19/new-job-sp1.aspx</link><pubDate>Tue, 19 Dec 2006 20:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1327052</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/freik/comments/1327052.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=1327052</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=1327052</wfw:comment><description>&lt;P&gt;I recently switched from the lead of the Code Gen &amp;amp; Tools team for Visual C++ to the lead for the Code Gen team for the .Net Framework.&amp;nbsp; I've not used managed code much, but for some classes of code, it sure does look easier to use [I'm working on a goofy GUI app for my personal use in C# that took me forever to do in C++].&amp;nbsp; There are lots of interesting problems to solve in this space, and a dramatically different set of customer constraints &amp;amp; potential customer scenarios.&amp;nbsp; I have to admit the security concerns for a JIT in the ASP.NET world are a little bit unnerving...&lt;/P&gt;
&lt;P&gt;In far more interesting news, VS 2005 SP1 just released.&amp;nbsp; OK, it actually released a few days ago, but my power didn't come back on from our nasty storm Thursday night until Monday, so I was a bit preoccupied.&amp;nbsp; I highly recommend picking this up if you're using the AMD64 compiler.&amp;nbsp; We shipped an awful lot of compiler fixes, along with a few code quality improvements, in this release.&amp;nbsp; You'll notice that prologues and epilogues of complex functions look much different, and that the compiler throughput (the amount of time it takes to compile a function) is a bit better.&amp;nbsp; There are some severe bugs in the PGO scenario {Profile Guided Optimization} that anyone using this feature really needs.&amp;nbsp; Aside from that, I hear that the VS experience is just much more pleasant than VS 2005 RTM.&amp;nbsp; Go forth and &lt;A class="" title="Download SP1" href="http://www.microsoft.com/downloads/details.aspx?familyid=BB4A75AB-E2D4-4C96-B39D-37BAF6B5B1DC&amp;amp;displaylang=en" target=_blank mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=BB4A75AB-E2D4-4C96-B39D-37BAF6B5B1DC&amp;amp;displaylang=en"&gt;Download!&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Anyway, I'll try to get some more interesting blogs posts going in the future - work seems to have calmed down quite a bit, since Vista finally shipped.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1327052" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item><item><title>Speaking in 'public'...</title><link>http://blogs.msdn.com/freik/archive/2006/10/17/speaking-in-public.aspx</link><pubDate>Wed, 18 Oct 2006 06:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:837679</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/freik/comments/837679.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=837679</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=837679</wfw:comment><description>&lt;P&gt;I'll be hanging out with the &lt;EM&gt;cool &lt;/EM&gt;kids at the &lt;A class="" title="Northwest C++ Users Group" href="http://www.nwcpp.org/" target=_blank mce_href="http://www.nwcpp.org"&gt;Northwest C++ Users Group&lt;/A&gt;&amp;nbsp;tomorrow night.&amp;nbsp; If you're in the area, and want to heckle me, swing by.&amp;nbsp; We'll be in building 40 at 6:30 PM.&amp;nbsp; My talk starts at 7:00 PM.&amp;nbsp; I'm talking about the actual runtime cost of exception handling for x64 and x86 on Windows.&lt;/P&gt;
&lt;P&gt;Update:&lt;/P&gt;
&lt;P&gt;Check out &lt;A href="http://www.nwcpp.org/Meetings/2006/10.html"&gt;http://www.nwcpp.org/Meetings/2006/10.html&lt;/A&gt;&amp;nbsp;for the slides, and a video of the talk, if you're interested.&amp;nbsp; You can see my thinning hair in back, my marvelous posture, and my always entertaining speaking style.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=837679" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category><category domain="http://blogs.msdn.com/freik/archive/tags/X64+ABI+Info/default.aspx">X64 ABI Info</category></item><item><title>A more flexible array template [and the evolution of the idea]</title><link>http://blogs.msdn.com/freik/archive/2006/09/18/a-more-flexible-array-template-and-the-evolution-of-the-idea.aspx</link><pubDate>Tue, 19 Sep 2006 00:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:734072</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/freik/comments/734072.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=734072</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=734072</wfw:comment><description>&lt;P mce_keep="true"&gt;{Disclaimer - I started with a bunch of code from boost::array - it's a great implementation of the functionality it provides}&lt;/P&gt;
&lt;P mce_keep="true"&gt;While my day job doesn't generally allow me to goof around with advanced C++ features, I still managed to find time to do so after the kids are in bed.&amp;nbsp; Mark &amp;amp; I were talking about&amp;nbsp; a new feature in C99: variable length arrays.&amp;nbsp; They're incredibly useful for certain scenarios, and will, by most compilers I imagine, just get turned into an _alloca call.&amp;nbsp; This led to a discussion of the value of variable sized arrays, and to categorize them.&amp;nbsp; Here's the final result:&lt;/P&gt;
&lt;P mce_keep="true"&gt;Type 1: Fixed size arrays:&amp;nbsp; Easy to do in C, boost::array&amp;lt;T, N&amp;gt; does it for C++ with all the bells &amp;amp; whistles of an STL container [tr1 has something awfully similar]&lt;BR&gt;Type 2: Variable length arrays:&amp;nbsp;&amp;nbsp;&amp;nbsp; Hard to do in C, std::vector&amp;lt;T&amp;gt; does it for C++&lt;BR&gt;Type 3: Variable sized arrays at construction time:&amp;nbsp; Easy to do in C (malloc or _alloca always produce these), doesn't exist currently in either boost or STL&lt;/P&gt;
&lt;P mce_keep="true"&gt;When we started comparing these things, we came to the conclusion that C99 style variable length arrays would be very useful.&amp;nbsp; Using __forceinline and _alloca, you can produce an implementation that works for any scenario that stays in a single function scope.&amp;nbsp; As soon as you start working across scopes, or try to implement something as a global, it falls to pieces.&amp;nbsp; It also fails miserably if the compiler doesn't actually inline forceinline functions [which is the case for -Od, and anything with -Ob0].&amp;nbsp; And I don't have a very reliable way of detecting this scenario :-(&lt;/P&gt;
&lt;P mce_keep="true"&gt;Ignoring the weaknesses, let's assume that the programmer is very intelligent and all-knowing, and will never accidentally abuse these routines.&amp;nbsp; Here's an initial implementation (just the part that matters) that supports stack-based allocation of both Type 1 and Type 3 arrays:&lt;/P&gt;&lt;FONT face=Courier size=2&gt;
&lt;P mce_keep="true"&gt;template&amp;lt;typename T, std::size_t N = 0&amp;gt;&lt;BR&gt;class array : public impl::_common_array&amp;lt;T, array&amp;lt;T,N&amp;gt; &amp;gt; {&lt;BR&gt;protected:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; friend impl::_common_array&amp;lt;T, array&amp;lt;T,N&amp;gt; &amp;gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T elems[N];&amp;nbsp;&amp;nbsp;&amp;nbsp; // fixed-size array of elements of type T&lt;/P&gt;
&lt;P mce_keep="true"&gt;public:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array(std::size_t n = N) { BOOST_ASSERT(n == N); }&lt;BR&gt;};&lt;BR&gt;&amp;nbsp;&lt;BR&gt;template&amp;lt;typename T&amp;gt;&lt;BR&gt;class array&amp;lt;T, 0&amp;gt; : public impl::_common_array&amp;lt;T, array&amp;lt;T,0&amp;gt; &amp;gt; {&lt;BR&gt;protected:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; friend impl::_common_array&amp;lt;T, array&amp;lt;T,0&amp;gt; &amp;gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T *elems;&lt;BR&gt;public:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __forceinline array(std::size_t s) : sz(s), elems((T*)_alloca(sizeof(T)*s) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; s; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T *temp = new(&amp;amp;elems[i]) T;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~array() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; sz; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elems[i].~T();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;};&lt;/P&gt;&lt;/FONT&gt;
&lt;P mce_keep="true"&gt;But I don't like allowing a programmer to shoot themselves in the foot accidentally (on purpose is fine :-)).&amp;nbsp; First, I added some code so that we don't try stack-allocation for DEBUG code, since the inliner is rarely enabled for that scenario.&amp;nbsp; Next I promoted a warning to an error so that if the routine ever doesn't get inlined, you'll fail.&amp;nbsp; Finally, I declared a private operator new, so that you can't construct one of these things on the heap and really screw up the world:&lt;/P&gt;&lt;FONT face=Courier size=2&gt;
&lt;P mce_keep="true"&gt;template&amp;lt;class T&amp;gt;&lt;BR&gt;class array&amp;lt;T, 0&amp;gt; : public impl::_common_array&amp;lt;T, array&amp;lt;T,0&amp;gt; &amp;gt; {&lt;BR&gt;private:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void *operator new(std::size_t sz);&lt;BR&gt;protected:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; friend impl::_common_array&amp;lt;T, array&amp;lt;T,0&amp;gt; &amp;gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T *elems;&lt;BR&gt;public:&lt;BR&gt;#if defined(_DEBUG) || defined(DEBUG)&lt;BR&gt;&amp;nbsp;&lt;BR&gt;#pragma message("Using lame implementation")&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array(std::size_t sz) : sz(sz), elems(new T[sz]) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~array() {delete[] elems;}&lt;BR&gt;&amp;nbsp;&lt;BR&gt;#elif !defined(NODEBUG) &amp;amp;&amp;amp; !defined(NDEBUG) &amp;amp;&amp;amp; !defined(_NODEBUG)&lt;BR&gt;&amp;nbsp;&lt;BR&gt;#pragma message("Be sure that your optimized build is NOT using -Ob0 - this completely disables inlining")&lt;BR&gt;#pragma error("Please define DEBUG or _DEBUG for your debug build, and NODEBUG, NDEBUG or _NODEBUG for your optimizing build, otherwise, this code won't work!")&lt;BR&gt;&amp;nbsp;&lt;BR&gt;#else&lt;BR&gt;&amp;nbsp;&lt;BR&gt;#pragma message("Using good implementation")&lt;BR&gt;#pragma warning(error:4714)&lt;BR&gt;#pragma optimize("b1", on)&lt;BR&gt;#pragma auto_inline(on)&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // If this thing doesn't get inlined, the code won't work - you'll need to use the previous blob of code instead&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __forceinline array(std::size_t sz) : sz(sz), elems((T*)_alloca(sizeof(T)*sz))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; sz; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T* temp = new(&amp;amp;elems[i]) T;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~array() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; sz; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elems[i].~T();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;};&lt;/P&gt;&lt;/FONT&gt;
&lt;P mce_keep="true"&gt;But I'd really like to allow these things to be a bit more general purpose!&amp;nbsp; Fact is, a tricky optimizer could turn a malloc/free into an alloca, and a fixed-size alloca into a zero-cost part of the stack frame adjustment.&amp;nbsp; But getting the compiler to decide that a variable sized malloc should be turned into an alloca seems error-prone.&amp;nbsp; What if I want an array of 4Mb?&lt;BR&gt;There goes my stack - poof - in one fell swoop.&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, now, I'm headed to some sort of policy based memory allocation where the programmer could indicate that stack allocation should be used.&lt;/P&gt;
&lt;P mce_keep="true"&gt;It's still unsafe, but not automatically so.&amp;nbsp; The programmer is the one who should understand the implications of the malloc/free -&amp;gt; alloca conversion.&amp;nbsp; If there is no allocated memory, we'll just new &amp;amp; delete the memory manually.&amp;nbsp; So, instead of auto-allocating memory on the stack, we'll allow the programmer to allocate memory that they wish to keep track of manually, or, if no memory is provided, we'll allocate it from the heap, and free it when the object is destroyed.&lt;/P&gt;&lt;FONT face=Courier size=2&gt;
&lt;P mce_keep="true"&gt;namespace kbf&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; namespace impl &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename T, class CHILD&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class _common_array &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __forceinline CHILD *downcast() { return (CHILD *)this; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __forceinline const CHILD *downcast() const { return (const CHILD *)this; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // type definitions&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef T&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value_type;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef T*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; iterator;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef const T*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_iterator;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef T&amp;amp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reference;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef const T&amp;amp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reference;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef std::size_t&amp;nbsp;&amp;nbsp;&amp;nbsp; size_type;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef std::ptrdiff_t difference_type;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef std::reverse_iterator&amp;lt;iterator&amp;gt; reverse_iterator;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typedef std::reverse_iterator&amp;lt;const_iterator&amp;gt; const_reverse_iterator;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // iterator support&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; iterator&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; begin()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { return downcast()-&amp;gt;elems; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_iterator&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; begin()&amp;nbsp; const { return downcast()-&amp;gt;elems; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; iterator&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { return downcast()-&amp;gt;elems+downcast()-&amp;gt;size(); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_iterator&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end()&amp;nbsp;&amp;nbsp;&amp;nbsp; const { return downcast()-&amp;gt;elems+downcast()-&amp;gt;size(); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reverse_iterator&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rbegin()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { return reverse_iterator(downcast()-&amp;gt;end()); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reverse_iterator&amp;nbsp; rbegin() const { return const_reverse_iterator(downcast()-&amp;gt;end()); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reverse_iterator&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rend()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { return reverse_iterator(begin()); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reverse_iterator&amp;nbsp; rend()&amp;nbsp;&amp;nbsp; const { return const_reverse_iterator(begin()); }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // at() with range check&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reference&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at(size_type i)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { rangecheck(i); return downcast()-&amp;gt;elems[i]; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reference at(size_type i) const { rangecheck(i); return downcast()-&amp;gt;elems[i]; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // front() and back()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reference&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; front()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { return c_array()[0]; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reference front() const { return data()[0]; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reference&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; back()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { return c_array()[downcast()-&amp;gt;size()-1]; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reference back()&amp;nbsp; const { return data()[downcast()-&amp;gt;size()-1]; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // direct access to data (read-only)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const T* data() const { return downcast()-&amp;gt;elems; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // use array as C array (direct read/write access to data)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T* c_array() { return downcast()-&amp;gt;elems; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // assign one value to all elements&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void assign (const T&amp;amp; value) { std::fill_n(begin(),downcast()-&amp;gt;size(),value); }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // check range (may be private because it is static)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void rangecheck (size_type i) const {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (i &amp;gt;= downcast()-&amp;gt;size()) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw std::range_error("array&amp;lt;&amp;gt;: index out of range");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // operator[]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; reference operator[](size_type i) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BOOST_ASSERT( i &amp;lt; downcast()-&amp;gt;size() &amp;amp;&amp;amp; "out of range" ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return c_array()[i];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const_reference operator[](size_type i) const &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BOOST_ASSERT( i &amp;lt; downcast()-&amp;gt;size() &amp;amp;&amp;amp; "out of range" ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return data()[i]; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N = 0&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class array : public impl::_common_array&amp;lt;T, array&amp;lt;T,N&amp;gt; &amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; friend impl::_common_array&amp;lt;T, array&amp;lt;T,N&amp;gt; &amp;gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T elems[N];&amp;nbsp;&amp;nbsp;&amp;nbsp; // fixed-size array of elements of type T&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array(std::size_t n = N) { BOOST_ASSERT(n == N); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // size is constant&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static size_type size() { return N; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static bool empty() { return false; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static size_type max_size() { return N; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // swap (note: linear complexity)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void swap (array&amp;lt;T,N&amp;gt;&amp;amp; y) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::swap_ranges(begin(),end(),y.begin());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // assignment with type conversion&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename T2&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array&amp;lt;T,N&amp;gt;&amp;amp; operator= (const array&amp;lt;T2,N&amp;gt;&amp;amp; rhs) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::copy(rhs.begin(),rhs.end(), begin());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return *this;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class array&amp;lt;T, 0&amp;gt; : public impl::_common_array&amp;lt;T, array&amp;lt;T,0&amp;gt; &amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO:&amp;nbsp; This needs to be noncopyable, probably, or deep-copyable...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void *operator new(size_t);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; friend impl::_common_array&amp;lt;T, array&amp;lt;T,0&amp;gt; &amp;gt;;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::size_t sz:sizeof(std::size_t) * 8 - 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned int releaseMem : 1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T *elems;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array(std::size_t s, void *memory = NULL) : sz(s), releaseMem(!memory), elems((T*)memory) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (releaseMem)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memory = malloc(s * sizeof(T));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elems = (T*)memory;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; s; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T *temp = new(&amp;amp;elems[i]) T;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array(std::size_t s, const T &amp;amp;copyVal, void *memory = NULL) : sz(s), releaseMem(!memory), elems((T*)memory) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (releaseMem)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memory = malloc(s * sizeof(T));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elems = (T*)memory;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; s; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T *temp = new(&amp;amp;elems[i]) T(copyVal);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~array() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (size_t i = 0; i &amp;lt; sz; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elems[i].~T();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (releaseMem)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; free(elems);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // size is constant&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size_type size() const { return sz; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool empty() const { return sz != 0; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size_type max_size() const { return sz; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // swap (note: linear complexity)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; void swap (array&amp;lt;T,0&amp;gt;&amp;amp; y) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // error check&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::swap_ranges(begin(),end(),y.begin());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // assignment with type conversion&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; template &amp;lt;typename T2&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array&amp;lt;T,0&amp;gt;&amp;amp; operator= (const array&amp;lt;T2,0&amp;gt;&amp;amp; rhs) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BOOST_ASSERT(rhs.size() == this-&amp;gt;size());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::copy(rhs.begin(),rhs.end(), begin());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return *this;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // comparisons&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool operator== (const array&amp;lt;T,N&amp;gt;&amp;amp; x, const array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return std::equal(x.begin(), x.end(), y.begin());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool operator&amp;lt; (const array&amp;lt;T,N&amp;gt;&amp;amp; x, const array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool operator!= (const array&amp;lt;T,N&amp;gt;&amp;amp; x, const array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return !(x==y);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool operator&amp;gt; (const array&amp;lt;T,N&amp;gt;&amp;amp; x, const array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return y&amp;lt;x;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool operator&amp;lt;= (const array&amp;lt;T,N&amp;gt;&amp;amp; x, const array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return !(y&amp;lt;x);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool operator&amp;gt;= (const array&amp;lt;T,N&amp;gt;&amp;amp; x, const array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return !(x&amp;lt;y);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // global swap()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; template&amp;lt;typename T, std::size_t N&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; inline void swap (array&amp;lt;T,N&amp;gt;&amp;amp; x, array&amp;lt;T,N&amp;gt;&amp;amp; y) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x.swap(y);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/FONT&gt;
&lt;P mce_keep="true"&gt;} /* namespace kbf */&lt;/P&gt;
&lt;P mce_keep="true"&gt;This is where I am currently.&amp;nbsp; &lt;BR&gt;This seems incredibly useful, and still very performant.&lt;BR&gt;What I'd really like is to be able to eliminate vectors from most of my code, and use these things unless I really do need growable vectors...&lt;/P&gt;
&lt;P mce_keep="true"&gt;I'm working on writing something up about how to use chained unwind info next, hopefully that won't be quite so long in coming as this post...&lt;/P&gt;
&lt;P mce_keep="true"&gt;-Kev&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=734072" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item><item><title>How to get CL.exe proxy filters (like STLFilt) working under VS2005</title><link>http://blogs.msdn.com/freik/archive/2006/04/05/how-to-get-cl-exe-proxy-filters-like-stlfilt-working-under-vs2005.aspx</link><pubDate>Wed, 05 Apr 2006 18:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:569025</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/freik/comments/569025.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=569025</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=569025</wfw:comment><description>&lt;P&gt;There's a class of tools that lots of people write that replace cl.exe with a 'wrapper' to do things link pre-process a command line [perhaps adding particular -D arguments], or filtering the output to deal with things like psychotically complicated error messages from template metaprogramming. These tools tend to be incredibly useful, and also tend to be incredibly straightforward to author. And with VS2005, they tend to be broken when running under the IDE. With 2005, the compiler toolset finally got serious about supporting Unicode. You can write code in Unicode (so you can have variable names like "a picture of a telephone" :-) ) You should also get your error messages in Unicode. The trouble arises when you realize the ethnocentric history of software. It's the stomping ground of the English-speaking white male. I'm not trying to be rude, racist, sexist, or generally offensive, I'm just speaking historically (and unfortunately, it continues to be a field dominated by men, though the few women I &lt;EM&gt;have&lt;/EM&gt; been able to work with are truly brilliant). Whoops - get off that tangent and back to the point... The Win32 console file handles cannot handle Unicode. They're code-page based handles, so when you're running under the console, we just spit out code-page based errors &amp;amp; warnings. If those errors &amp;amp; warnings contain Unicode, you're just out of luck. Well, when cl.exe is running under the IDE, we figured we could improve the experience. Instead of spitting messages out stdout and stderr, we open up some named pipes, and spit out Unicode that the IDE can then display. Which is great, until you start thinking about the cl.exe proxy scenario. So, if you're writing a cl.exe proxy, prior to invoking the original cl.exe, undefine VS_UNICODE_OUTPUT. This successfully tricks cl.exe into thinking you're just compiling from the command line, and you're back in business (with non-Unicode messages, though :-( )&lt;/P&gt;
&lt;P&gt;Update:&amp;nbsp; Leor Zolman (Mr. STLFilt himself!) mentioned he couldn't get this working.&amp;nbsp; Turns out there's one more little issue that you may not realize:&amp;nbsp; The response files being fed to cl.exe are probably unicode.&amp;nbsp; You have to uncheck that, or else handle unicode response files for everything to work properly.&amp;nbsp; If you turn off 'Use Unicode Response Files" in your project, go grab the source to STLFilt and change the doWin32Stuff function to have this at the beginning:&lt;/P&gt;&lt;PRE&gt;// from cl.cpp:
int doWin32Stuff(char *full_filt_cmd, char *cmdline)
{
    using namespace std;
    if (getenv("VS_UNICODE_OUTPUT"))
    {
        log("VS_UNICODE_OUTPUT is enabled - disabling!");
        // Clear the Unicode output flag to force the compiler to use the normal output pipes
        // I don't know perl at all, but this is how you do it from C:
        _putenv("VS_UNICODE_OUTPUT=");
    }
&lt;/PRE&gt;
&lt;P&gt;-Kev &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=569025" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item><item><title>x64 ABI vs. x86 ABI (aka Calling Conventions for AMD64 &amp; EM64T)</title><link>http://blogs.msdn.com/freik/archive/2006/03/06/X64-calling-conventions-summary.aspx</link><pubDate>Tue, 07 Mar 2006 02:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:398200</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/freik/comments/398200.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=398200</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=398200</wfw:comment><description>&lt;P&gt;(This is an older post, with some mild cleanup, and fixed links)&lt;/P&gt;
&lt;P&gt;Before I start: ABI = Application Binary Interface – this is the spec that describes how to call functions, pass parameters, unwind the stack, handle exceptions, etc... It’s also sometimes call the ‘Calling Convention’&lt;/P&gt;
&lt;P&gt;There is a persistent misconception among people who are implementing x64 compilers/code generators, and folks that write ASM code for x64, who have a functioning solution for x86. People too frequently assume they can just keep most of their code, while changing ESP to RSP, and things should 'just work'. This is fundamentally not true. When initially working on the x64 ABI, it was decided that we wanted to clean up the way that exception handling &amp;amp; general function invocation worked. We had a brand new architecture, we wanted to cut out all of the legacy junk that continually prevents, or at least overcomplicates, achieving great performance on the x86 platform. With this in mind, x64 was given a single calling convention – no __cdecl / __stdcall / __fastcall / __thiscall mess. There was also a dramatic change in the way that x64 unwinds the stack, compared to how x86 does it.&lt;/P&gt;
&lt;P&gt;Unwinding the stack is used in a wide variety of places, including handling exceptions, garbage collection, and displaying the call stack from a debugger. On x86, every function that needs some sort of attention due to an exception must add an element to a thread-global linked list upon entry, and remove it upon exit. For non-exception unwinds, the thing doing the unwind must grok through some nasty meta-data that tries to describe what &amp;amp; when the compiler is setting up the stack frame. This meta-data was only implemented after about 1999, and is primarily supported in debuggers. I’ll be ignoring this junk, and instead focus on how exception handling works, since this is the primary way your code will break if you don’t get this right (undebuggable code is still broken, but you won’t notice until you try to get a stack trace).&lt;/P&gt;
&lt;P&gt;So, the x86 thread-global linked list contains a list of structures, each element of such contains a function pointer to call in the event of an exception, and then some data that said function will consume. Thus, you’ll see fs:[0] references scattered throughout C++ code:every function that contains a destructor that must be invoked if an exception occurs must have one of these things. When your code creates a new object, there is a small bit of code executed to update the data on this thread-global list element. When that object is destroyed, more code is executed. Because of this, x86 can catch hundreds of thousands of exceptions per second, but if you don’t actually take any exceptions, your CPU executes lots of blobs of code that have no purpose except to be sure that the rare exception is handled properly. Finding the first function that needs to handle an exception, or destroy an object is an O(1) operation: it’s a single lookup of FS:[0]. VERY fast. Unfortunately, that should &lt;I&gt;not&lt;/I&gt; be a common scenario. Exceptions should be exceptional, not common!In addition, this linked list really resides on the stack, thus there is a function pointer sitting right below the return address on your stack!Buffer overruns, anyone?There is now an extra blob of information that indicates what functions are valid to be invoked as exception handlers (link /SAFESEH, if you’re curious), but this is only used if every contribution to your .exe or .dll has this information.&lt;/P&gt;
&lt;P&gt;With this in mind, on x64 every function has a very strict structure that must be properly described in static data. The prolog is the only place in which you can adjust your stack frame pointer. The prolog can only be up to 255 bytes long. All modifications of your stack frame pointer, as well as all saves of nonvolatile registers (RBP, RSI, RDI, R12-R15, XMM6-XMM15) must be described in this static data, so that they can be restored correctly if an exception occurs. If you function is missing this static data, and an exception is raised, the thread will be terminated by the OS.&lt;/P&gt;
&lt;P&gt;In an effort to get stuff into peoples hands, here’s an excerpt that I’ve prepended to the ABI document that has not yet seen the light of day. I’ve updated the links to point you &lt;/P&gt;
&lt;P&gt;at the sections on MSDN. Rather than posting the whole thing, I've just put in my description, with links back to the slightly older version on MSDN. The current version has some more detail, but nothing you couldn't figure out through, ahem, trial &amp;amp; error...&lt;/P&gt;
&lt;P&gt;&amp;lt;snip&amp;gt;&lt;/P&gt;
&lt;H2&gt;Overview&lt;/H2&gt;
&lt;P&gt;The in depth nature of an ABI document doesn’t lend itself to ‘easy reading’. However, it is the case that a detailed knowledge of the entire ABI is rarely necessary to accomplish most programming tasks. This section is simply a quick overview of the ABI, with pointers to the sections that describe the various aspects in more detail. It also tries to point out particular ‘gotchas’ that must be strictly adhered to, in an effort to minimize the problems encountered.&lt;/P&gt;
&lt;H3&gt;Calling convention&lt;/H3&gt;
&lt;P&gt;The x64 Windows ABI is a 4 register ‘fast-call’ calling convention, with stack-backing for those registers. There is a strict one-to-one correspondence between arguments in a function, and the registers for those arguments. &lt;I&gt;Any argument that doesn’t fit in 8 bytes, or is not 1, 2, 4, or 8 bytes, must be passed by reference. &lt;/I&gt;There is no attempt to spread a single argument across multiple registers. The x87 register stack is unused. It may be used, but must be considered volatile across function calls. All floating point operations are done using the 16 XMM registers. The arguments are passed in registers RCX, RDX, R8, and R9. If the arguments are float/double, they are passed in XMM0L, XMM1L, XMM2L, and XMM3L. &lt;I&gt;16 byte arguments are passed by reference&lt;/I&gt;. Parameter passing is described in detail at &lt;A href="http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx" mce_href="http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Calling Convention: Parameter Passing&lt;/A&gt;. In addition to these registers, RAX, R10, R11, XMM4, and XMM5 are volatile. All other registers are non-volatile. Register usage is documented in detail at &lt;A href="http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx" mce_href="http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Register Usage&lt;/A&gt; and &lt;A href="http://msdn.microsoft.com/en-us/library/6t169e9c.aspx" mce_href="http://msdn.microsoft.com/en-us/library/6t169e9c.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Calling Convention: Caller/Callee Saved Registers&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;The caller is responsible for allocating space for parameters to the callee, and &lt;I&gt;must always allocate sufficient space for the 4 register parameters, even if the callee doesn’t have that many parameters. &lt;/I&gt;This aids in the simplicity of supporting K&amp;amp;R C’s unprototyped functions, and ‘vararg’ C/C++ functions. For vararg/unprototyped functions any float values must be duplicated in the corresponding general-purpose register. Any parameters above the first 4 must be stored on the stack, above the backing-store for the first 4, prior to the call. Vararg function details can be found at &lt;A href="http://msdn.microsoft.com/en-us/library/dd2wa36c.aspx" mce_href="http://msdn.microsoft.com/en-us/library/dd2wa36c.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Calling Convention: Varargs&lt;/A&gt;. Unprototyped function information is detailed at &lt;A href="http://msdn.microsoft.com/en-us/library/6yy8aw4d.aspx" mce_href="http://msdn.microsoft.com/en-us/library/6yy8aw4d.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Calling Convention: Unprototypesd Functions&lt;/A&gt;.&lt;/P&gt;
&lt;H3&gt;Alignment&lt;/H3&gt;
&lt;P&gt;&lt;I&gt;Most structures are aligned to their natural alignment.&lt;/I&gt; The primary exceptions are the stack pointer and malloc/alloca memory, which are aligned to 16 byte, in order to aid performance. Alignment above 16 bytes must be done manually, but since 16 bytes is a common alignment size for XMM operations, this should suffice for most code. For more information about structure layout and alignment see &lt;A href="http://msdn.microsoft.com/en-us/library/02c56cw3.aspx" mce_href="http://msdn.microsoft.com/en-us/library/02c56cw3.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Types and Storage&lt;/A&gt;. For information about the stack layout, see &lt;A href="http://msdn.microsoft.com/en-us/library/x4ea06t0.aspx" mce_href="http://msdn.microsoft.com/en-us/library/x4ea06t0.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Stack Usage&lt;/A&gt;.&lt;/P&gt;
&lt;H3&gt;Unwindability&lt;/H3&gt;
&lt;P&gt;All non-leaf functions [functions that neither call a function, nor allocate any stack space themselves] must be annotated with data [referred to as xdata or ehdata, which is pointed to from pdata] that describes to the operating system how to properly unwind them, to recover non-volatile registers. Prologs &amp;amp; epilogs are highly restricted, so that they can be properly described in xdata. The stack pointer must be aligned to 16 bytes, except for leaf functions, in any region of code that isn’t part of an epilog or prolog. For details about the proper structure of function prolog &amp;amp; epilogs, see &lt;A href="http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx" mce_href="http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Prolog and Epilog&lt;/A&gt;. For more information about exception handling, and the exception handling/unwinding pdata &amp;amp; xdata see &lt;A href="http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx" mce_href="http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions: Exception Handling (x64)&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;lt;/snip&amp;gt;&lt;/P&gt;
&lt;P&gt;Anyway, I hope that helps. I could not &lt;I&gt;believe&lt;/I&gt; how long it took to find this stuff on MSDN. For some (lame) reason, blogs are better indexed than MSDN in both MSN search, and Google. Hopefully this entry will make finding this information easier.&lt;/P&gt;
&lt;P&gt;Here’s a link to the official x64 ABI documentation, which goes into excruciating detail about this stuff. Sorry if it’s not very readable – I wrote a few parts, along with a few other people, and we’re primarily engineers, not writers. We have had a great UE write take over on this document, and it should be slightly improved when it sees the light of day as part of the VS 2005 documentation, but until then, this is it:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx" mce_href="http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx"&gt;MSDN Library: Dev Tools and Languages: VS2008: VS: VC++: 64-bit Programming: x64 Software Conventions&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Hopefully, that link will continue to work for a while. MSDN likes to occasionally restructure the way it references information, just to keep us all on our toes. &lt;EM&gt;I've now updated the links 3 times. If they're broken, please ping me and I'll update them!&lt;/EM&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=398200" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category><category domain="http://blogs.msdn.com/freik/archive/tags/X64+ABI+Info/default.aspx">X64 ABI Info</category></item><item><title>Why isn't __assume on for asserts in retail mode?</title><link>http://blogs.msdn.com/freik/archive/2006/01/30/519814.aspx</link><pubDate>Tue, 31 Jan 2006 01:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:519814</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/freik/comments/519814.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=519814</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=519814</wfw:comment><description>&lt;p&gt;&lt;font face="Courier New"&gt;__assume&lt;/font&gt; and &lt;font face="Courier New"&gt;__forceinline&lt;/font&gt; were the first two features I implemented as a developer out of college.&amp;nbsp; I just resolved a bug as 'By Design' that asked the question posed in the title.&amp;nbsp; Here's a brief explanation:&lt;/p&gt;
&lt;p&gt;First, &lt;font face="Courier New"&gt;__assume(n==x)&lt;/font&gt; basically tells the expression optimizer &amp;amp; the global optimizer in the compiler that n is being assigned the value of x.&amp;nbsp; So, if you say __assume(n==5);y=n*n; the compiler will automagically turn that into y=25.&amp;nbsp; Nifty, right?&amp;nbsp; It's also used to flag dead code:&lt;/p&gt;
&lt;pre&gt;switch(i) {
case 1:
case 2:
    printf("Hello\n");
    break;
default:
    __assume(0);
}&lt;/pre&gt;
&lt;p&gt;For that switch, there will be no checks for any values other than 1 or 2 - no range check.&amp;nbsp; Again, in performance sensitive code, this can be a big win.&lt;/p&gt;
&lt;p&gt;However, the transformation of assert to __assume could have potentially negative impact on security, so it's not defined by default.&amp;nbsp; Individual customers should determine if it's an acceptable optimization.&lt;/p&gt;
&lt;p&gt;The trouble lies in the potential lack of code coverage testing.&amp;nbsp; Here's a simplistic case to illustrate the problem:&lt;/p&gt;
&lt;pre&gt;
void untestedFunctionFoo()
{
    assert(passwordAlreadyChecked == true);
    // Assert is actually false,
    // but we don't realize that,
    // because we haven't tested it
    DoSomethingThatChecksSecurity();
}

void DoSomethingThatChecksSecurity()
{
    if (!passwordAlreadyChecked)
        GetPassword();
    doSomethingSecure();
}
&lt;/pre&gt;
&lt;p&gt;If the compiler inlines &lt;font face="Courier New"&gt;DoSomethingThatChecksSecurity&lt;/font&gt; into &lt;font face="Courier New"&gt;untestedFunctionFoo&lt;/font&gt;, and assert is turned into &lt;font face="Courier New"&gt;__assume(passwordAlreadyChecked == true) &lt;/font&gt;the optimizer will remove the call to &lt;font face="Courier New"&gt;GetPassword()&lt;/font&gt;, and then &lt;font face="Courier New"&gt;untestedFunctionFoo&lt;/font&gt;, which wasn't tested, no longer requires a password to get it.&amp;nbsp; Your visual code reviews don't pick up that &lt;font face="Courier New"&gt;doSomethingSecure&lt;/font&gt; might occur without a password, because logically, you're assertting that the password has already been checked, or you're calling &lt;font face="Courier New"&gt;GetPassword&lt;/font&gt;.&lt;/p&gt;
&lt;p&gt;Hopefully, that explains the issue.&amp;nbsp; Please use __assume with caution.&amp;nbsp; It can be a performance win, but if you're authoring code with severe security concerns, you're better off without it.&lt;/p&gt;
&lt;p&gt;-Kev&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=519814" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item><item><title>X64 Unwind Information</title><link>http://blogs.msdn.com/freik/archive/2006/01/04/509372.aspx</link><pubDate>Thu, 05 Jan 2006 00:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:509372</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/freik/comments/509372.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=509372</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=509372</wfw:comment><description>&lt;FONT size=2&gt;
&lt;P&gt;I've had a fairly large number of e-mails with various people both inside &amp;amp; outside Microsoft explaining the AMD64 unwind data. I generally push them at the ABI documentation (which I've linked to in &lt;A href="/freik/archive/2005/03/17/398200.aspx"&gt;this&lt;/A&gt; entry). But the ABI documentation really requires a complete reading before you can really understand how the unwind information all fits together. So, in an attempt to make dealing with unwind information, I'm going to attempt a more 'chatty' explanation of unwind data.&lt;/P&gt;
&lt;P&gt;&lt;FONT size=4&gt;&lt;STRONG&gt;Background&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=3&gt;&lt;STRONG&gt;The 2 phase exception model&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Both Win32 &amp;amp; Win64 have a 2 phase exception model. The first phase walks the list of functions that _might_ handle an exception, asking them if they will _actually_ handle the particular exception that occurred (this is done by calling filter functions). During this phase, the filter functions either return EXCEPTION_CONTINUE_SEARCH (0) which indicates that this handler will not handle the exception, EXCEPTION_HANDLE_EXCEPTION (1), which indicates that this handler will handle the exception. One other option is EXCEPTION_RESUME_EXECUTION (-1) that I won't mention (look it up in MSDN if you're curious).&lt;/P&gt;
&lt;P&gt;&lt;FONT size=3&gt;&lt;STRONG&gt;Why do you need unwind data?&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;First, you should probably understand WHY the Windows AMD64 ABI requires unwind data. In Win32 x86 land, when an exception occurs, the OS just looks at a pointer at fs:0 which is the head of a linked list of information regarding what to do in the event of an exception. Each function that requires any sort of attention when an exception occurs needs to create a node on this linked list. This node must contain all information necessary to handle the two phase exception mechanism of Win32. For Windows for AMD64, the way the functions that need to be invoked during exception handling are discovered not by walking a linked list, but crawling the stack. Thus, the stack must _always_ be in a state that can be statically walked. To accomplish this, there are 2 fundamental issues: how to discover the stack frame size of a function, and how to recover non-volatile (aka caller saved) register values. This is exactly what AMD64 unwind data describes. The trouble most people run into, though, is that even if your function doesn't need to do anything if an exception occurs, the function may be called by a function that does, and it may then call a function that will throw an exception. If this is the case, when the exception is thrown, the function's stack frame must be fully described. As an added bonus, because all stack frames are accurately described, there's never any reason to use a frame pointer unless absolutely necessary due to something like _alloca or __declspec(align(&amp;gt;16)).&lt;/P&gt;
&lt;P&gt;So, even if you just have a tiny little function that only calls another function, you still need unwind data, or when an exception occurs, your process will simply be terminated.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT size=3&gt;OK, What is unwind data?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Simply put, it's a meta-language that describes what, when, and how a function's frame is built. There are opcodes that indicate when &amp;amp; by how much the stack pointer has been adjusted, when &amp;amp; where a non-volatile register has been saved, or when, where, and to what offset a frame pointer has been set. When you're writing assembly code for ML64, there are predefined macros to help describe this stuff:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;PROC FRAME [optional handler address]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.ALLOCSTACK size&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.PUSHFRAME [code]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.PUSHREG reg&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.SAVEREG reg, offset&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.SAVEXMM128 reg, offset&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.SETFRAME reg, offset&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;.ENDPROLOG&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Note that all those offsets are actually restricted to be properly aligned. The .SAVEREG offset must be a multiple of 8, while .SAVEXMM128 offset must be a multiple of 16. The .SETFRAME offset must be a multiple of 16, and must be between 16 and 240. In addition, all frame manipulation must be completed in the first 254 bytes of the function. If you want to push registers saves &amp;amp; restores further into the function, you must use chained unwind info, which will have to be the subject of another blog entry...&lt;/P&gt;
&lt;P&gt;Looking up the directives on MSDN will give you examples of how they're all used. If you feel like authoring code that conforms to the prologue unwind descriptors is restrictive, you'll love the epilogue requirements. All function epilogues must look like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;(optional) lea rsp, [frame ptr + frame size] or add rsp, frame size&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;pop reg (zero or more)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;ret (or jmp)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;No other instructions may occur betwen the first lea/add and the final jmp or ret. At first glance, this may seem like you can't restore any XMM registers. The trick is that all non-volatile registers except those that you want to restore using a pop must be restored prior to entry to the epilogue. The reason this works is that if the OS has to unwind an epilogue, it already has the correct values in all the registers except the ones that are restored via pop, so things really do work out well.&lt;/P&gt;
&lt;P&gt;One other note: if the final jmp isn't an ip-relative jmp, but an indirect jmp, it must be preceded by the REX prefix, to indicate to the OS unwind routines that the jump is headed outside of the function, otherwise, the OS assumes it's a jump to a different location inside the same function.&lt;/P&gt;
&lt;P&gt;From here, I think I might see what kind of questions pop up, and go from there. I'll also add a future entry to describe how to use chained unwind information to allow you to save registers later in the function that the first 254 bytes (although I _think_ this requires that you need to author your own .pdata &amp;amp; .xdata which is a whole lot more complicated...)&lt;/P&gt;
&lt;P&gt;-Kev&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=509372" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category><category domain="http://blogs.msdn.com/freik/archive/tags/X64+ABI+Info/default.aspx">X64 ABI Info</category></item><item><title>How to make a no-inline inline function (and why you might want to)</title><link>http://blogs.msdn.com/freik/archive/2005/10/26/485276.aspx</link><pubDate>Wed, 26 Oct 2005 21:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:485276</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/freik/comments/485276.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=485276</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=485276</wfw:comment><description>&lt;DIV&gt;The Windows folks had a problem with the AMD64 compiler last week.&amp;nbsp; The interference package is not quite as good as the x86 one, so when it sees something like this:&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;// header.h&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;inline void foo(int a, int b, int c)&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;{&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bar(&amp;amp;a, &amp;amp;b, &amp;amp;c);&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;// function.cpp&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;#include "header.h"&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;void func()&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;{&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foo(1,2,3);&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foo(4,5,6);&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;we inline foo into func twice, generate (because they're address is taken) temporary storage for 1,2,3 &amp;amp; 4,5,6,&amp;nbsp;but&amp;nbsp;then we don't realize that, because they're scope-local address&amp;nbsp;taken variables (so any global function that may be using these addresses after the end of the foo scope is broken), we should be able to pack the two sets of temp's together.&amp;nbsp; This resulted in a kernel stack overflow (very very very bad).&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;The solution is to prevent the compiler from ever inlining foo, so that the temps are never allocated in func's stack frame.&amp;nbsp; The trouble with this, is that if you remove the inline, and add a __declspec(noinline) to the foo implementation, each .C file that includes header.h gets a new copy of foo, and when you try to link, you get a multiply defined&amp;nbsp;symbol error.&amp;nbsp; For data, the proper way to handle this is with __declspec(selectany), which tells the linker that if you see multiple symbols all claiming to define the same name, just pick any one of them.&amp;nbsp; Except you can't use selectany on a function definition, only on a variable definition.&amp;nbsp; &lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;So, instead, you use __declspec(noinline) inline void foo(...).&amp;nbsp; While it's not intuitive (and kind of funny) what's going on, in order for inline functions to be defined in a header, they require the selectany attribute, so the compiler, when it sees the 'inline' C++ keyword, tags the function as&amp;nbsp;a 'selectany' section for the linker.&amp;nbsp; Problem solved!&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;The primary reasons I can see to do this, (besides the reason the Windows Kernel folks have), is if you want to have some mechanism in place that is completely handled in headers, but you don't want to bloat your code or you want to be able to see, from disassembly, where the function is being called.&amp;nbsp; Can someone come up with other reasons?&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=485276" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item><item><title>Boost &amp; BJam plus Web Chats coming up</title><link>http://blogs.msdn.com/freik/archive/2004/11/08/254180.aspx</link><pubDate>Tue, 09 Nov 2004 06:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:254180</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/freik/comments/254180.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=254180</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=254180</wfw:comment><description>&lt;P&gt;I'm a big C++ fan, despite the fact that the VC++ optimizer is written in C.&amp;nbsp; I've been using Boost for a couple years now, and just picked up the initial tarball for 1.32.0.&amp;nbsp; Someone's written a .jam file for VC8 on x64, but it just does the bare minimum - lots of warnings &amp;amp; whatnot.&amp;nbsp; I have written these for all 3 platforms and I've been tempted to try my hand at a PocketPC ARM &amp;amp; x86 version, too (since I fool around on those platforms, occasionally).&amp;nbsp; I haven't ever bothered testing the IA64 stuff, but I haven't had any problems with my x64 &amp;amp; x86 version.&amp;nbsp; I'll have to figure out if I can upload files here.&amp;nbsp; Anyway, for now I'll just toss in the x64 one I've got inline:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# Microsoft Visual C++&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# (C) Copyright David Abrahams 2001. Permission to copy, use,&lt;BR&gt;# modify, sell and distribute this software is granted provided this&lt;BR&gt;# copyright notice appears in all copies. This software is provided&lt;BR&gt;# "as is" without express or implied warranty, and with no claim as&lt;BR&gt;# to its suitability for any purpose.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;# The following #// line will be used by the regression test table generation&lt;BR&gt;# program as the column heading for HTML tables. Must not include version number.&lt;BR&gt;#//&amp;lt;a href="&lt;/FONT&gt;&lt;/A'&gt;&lt;FONT size=1&gt;http://msdn.microsoft.com/vstudio/default.asp"&amp;gt;Microsoft VC++&amp;lt;/a&lt;/FONT&gt;&lt;FONT size=1&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# singleton variables...&lt;BR&gt;set-as-singleton VC8_ROOT VC_SETUP ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# Get these variable set on the targets so that we can re-use the&lt;BR&gt;# build actions for other toolsets using this one as a base.&lt;BR&gt;flags vc80x64 VC_SETUP ;&lt;BR&gt;flags vc80x64 VC_COMPILER ;&lt;BR&gt;flags vc80x64 VC_LINKER ;&lt;BR&gt;flags vc80x64 VC_PDB_NAME ;&lt;BR&gt;&amp;nbsp; &lt;BR&gt;# compute vc80x64 tool path&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;VC8_ROOT = $(VS80COMNTOOLS:J=" ")"..\\..\\VC" ;&lt;BR&gt;VC8_ROOT = $(VC8_ROOT:J=" ") ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;VC_SETUP = "CALL \"$(VC8_ROOT)$(SLASH)vcvarsall.bat\" x86_amd64&amp;nbsp; &amp;gt;nul" ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;VC_COMPILER = cl ;&lt;BR&gt;VC_LINKER = link ;&lt;BR&gt;VC_PDB_NAME = vc80x64 ;&lt;BR&gt;VC_STDLIB_PATH = ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 CFLAGS &amp;lt;debug-symbols&amp;gt;on/&amp;lt;debug-store&amp;gt;object : /Z7 ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;debug-symbols&amp;gt;on/&amp;lt;debug-store&amp;gt;database : /Zi ;&lt;BR&gt;flags vc80x64 PDB_CFLAG &amp;lt;debug-symbols&amp;gt;on/&amp;lt;debug-store&amp;gt;database : /Fd ;&lt;BR&gt;flags vc80x64 PDB_LINKFLAG &amp;lt;debug-symbols&amp;gt;on/&amp;lt;debug-store&amp;gt;database : /PDB: ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;debug-symbols&amp;gt;on : /DEBUG ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# The linker disables the default optimizations when using /DEBUG. Whe have&lt;BR&gt;# to enable them manually for release builds with debug symbols.&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;debug-symbols&amp;gt;on/&amp;lt;runtime-build&amp;gt;release : /OPT:REF,ICF ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 CFLAGS &amp;lt;optimization&amp;gt;off : /Od ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;optimization&amp;gt;speed : /O2 ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;optimization&amp;gt;space : /O1 ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;inlining&amp;gt;off : /Ob0 ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;inlining&amp;gt;on : /Ob1 ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;inlining&amp;gt;full : /Ob2 ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;exception-handling&amp;gt;on : /EHsc ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;rtti&amp;gt;on : /GR ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# Note that these two options actually imply multithreading support on vc80x64&lt;BR&gt;# because there is no single-threaded dynamic runtime library. Specifying&lt;BR&gt;# &amp;lt;threading&amp;gt;multi would be a bad idea, though, because no option would be&lt;BR&gt;# matched when the build uses the default settings of &amp;lt;runtime-link&amp;gt;dynamic&lt;BR&gt;# and &amp;lt;threading&amp;gt;single.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 CFLAGS &amp;lt;runtime-build&amp;gt;release/&amp;lt;runtime-link&amp;gt;dynamic : /MD /GL ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;runtime-build&amp;gt;release/&amp;lt;runtime-link&amp;gt;dynamic : /LTCG ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;runtime-build&amp;gt;debug/&amp;lt;runtime-link&amp;gt;dynamic : /MDd ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;# VC8 doesn't support a single threaded runtime, just some single-threaded optimizations&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;runtime-build&amp;gt;release/&amp;lt;runtime-link&amp;gt;static/&amp;lt;threading&amp;gt;single : /MT /D_ST_MODEL ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;runtime-build&amp;gt;debug/&amp;lt;runtime-link&amp;gt;static/&amp;lt;threading&amp;gt;single : /MTd /D_ST_MODEL ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 CFLAGS &amp;lt;runtime-build&amp;gt;release/&amp;lt;runtime-link&amp;gt;static/&amp;lt;threading&amp;gt;multi : /MT ;&lt;BR&gt;flags vc80x64 CFLAGS &amp;lt;runtime-build&amp;gt;debug/&amp;lt;runtime-link&amp;gt;static/&amp;lt;threading&amp;gt;multi : /MTd ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 CFLAGS &amp;lt;cflags&amp;gt; ;&lt;BR&gt;flags vc80x64 C++FLAGS &amp;lt;cxxflags&amp;gt; ;&lt;BR&gt;flags vc80x64 DEFINES &amp;lt;define&amp;gt; ;&lt;BR&gt;flags vc80x64 UNDEFS &amp;lt;undef&amp;gt; ;&lt;BR&gt;flags vc80x64 HDRS &amp;lt;include&amp;gt; ;&lt;BR&gt;flags vc80x64 STDHDRS &amp;lt;sysinclude&amp;gt; ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;linkflags&amp;gt; ;&lt;BR&gt;flags vc80x64 ARFLAGS &amp;lt;arflags&amp;gt; ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 STDHDRS : $(VC8_ROOT)$(SLASH)include ;&lt;BR&gt;flags vc80x64 STDLIBPATH : $(VC8_ROOT)$(SLASH)lib$(SLASH)amd64 ;&lt;BR&gt;flags vc80x64 LIBPATH &amp;lt;library-path&amp;gt; ;&lt;BR&gt;flags vc80x64 NEEDLIBS &amp;lt;library-file&amp;gt; ;&lt;BR&gt;flags vc80x64 FINDLIBS &amp;lt;find-library&amp;gt; ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;target-type&amp;gt;$(SHARED_TYPES) : /DLL ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;flags vc80x64 LINKFLAGS &amp;lt;user-interface&amp;gt;console : /subsystem:console ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;user-interface&amp;gt;gui : /subsystem:windows ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;user-interface&amp;gt;wince : /subsystem:windowsce ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;user-interface&amp;gt;native : /subsystem:native ;&lt;BR&gt;flags vc80x64 LINKFLAGS &amp;lt;user-interface&amp;gt;auto : /subsystem:posix ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;rule vc-set-pdb-file ( targets + : name )&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; local pdb = $(targets[1]:B=$(name):S=.pdb) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VC_PDB_FILE on $(targets) = $(pdb:G=:R=$(LOCATE_TARGET)) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LOCATE on $(pdb) = $(LOCATE_TARGET) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Clean clean : $(pdb) ;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;#### Link ####&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;rule Link-action ( target implib ? : sources + : target-type ? )&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; with-command-file vc-Link $(&amp;lt;) : $(sources) $(NEEDLIBS) ;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gRUN_PATH($(&amp;lt;)) += $(VC_STDLIB_PATH) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if $(implib)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # incremental linking a DLL causes no end of problems: if the&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # actual exports don't change, the import .lib file is never&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # updated. Therefore, the .lib is always out-of-date and gets&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # rebuilt every time. I'm not sure that incremental linking is&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # such a great idea in general, but in this case I'm sure we&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # don't want it.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NOINCREMENTAL on $(&amp;lt;) = /INCREMENTAL:NO ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vc-set-pdb-file $(&amp;lt;) : $(target:B) ;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;actions together vc-Link&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_SETUP)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_LINKER) /nologo $(NOINCREMENTAL) $(LINKFLAGS) $(PDB_LINKFLAG)"$(VC_PDB_FILE)" /out:"$(&amp;lt;[1])" /IMPLIB:"$(&amp;lt;[2])" /LIBPATH:"$(LIBPATH)" /LIBPATH:"$(STDLIBPATH)" "$(FINDLIBS:S=.lib)" @"$(&amp;gt;)"&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;#### Cc #####&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;rule Cc-action&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vc-set-pdb-file $(&amp;lt;) : $(VC_PDB_NAME) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vc-Cc $(&amp;lt;) : $(&amp;gt;) ;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;actions vc-Cc&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_SETUP)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_COMPILER) /Zm800 -nologo -wd4996 -wd4103 -c -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" $(PDB_CFLAG)"$(VC_PDB_FILE)" -Fo"$(&amp;lt;)" "$(&amp;gt;)"&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;#### C++ ####&lt;BR&gt;rule C++-action&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vc-set-pdb-file $(&amp;lt;) : $(VC_PDB_NAME) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vc-C++ $(&amp;lt;) : $(&amp;gt;) ;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;actions vc-C++&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_SETUP)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_COMPILER) /Zm800 -nologo -wd4996 -wd4103 -EHsc -c -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" $(PDB_CFLAG)"$(VC_PDB_FILE)" -Fo"$(&amp;lt;)" -Tp"$(&amp;gt;)"&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;#### Archive ####&lt;BR&gt;rule Archive-action&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vc-set-pdb-file $(&amp;lt;) : $(&amp;lt;:B) ;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; with-command-file vc-Archive $(&amp;lt;) : $(&amp;gt;) ;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;actions vc-Archive&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_SETUP)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if exist "$(&amp;lt;)" DEL "$(&amp;lt;)"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(VC_LINKER) /lib $(ARFLAGS) $(PDB_LINKFLAG)"$(VC_PDB_FILE)" /out:"$(&amp;lt;)" @"$(&amp;gt;)"&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;That seems to work pretty well.&amp;nbsp; I haven't tried this with Beta 1 - I did the work @ home, but didn't test it until I got to work, so I only ran against a more recent build.&lt;/P&gt;
&lt;P&gt;Microsoft will be hosting an online chat November 9, 2004 at 9:00am Pacific Time to answer your Managed Code on 64-bit Windows Platforms questions.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/chats/"&gt;http://msdn.microsoft.com/chats/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/chats/outlook_reminders/04_MC_64BitWP_Nov9.ics"&gt;http://msdn.microsoft.com/chats/outlook_reminders/04_MC_64BitWP_Nov9.ics&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;And I'll be one of the hosts in this one on Wednesday, November 10th at 9AM PST:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/chats/outlook_reminders/04_MC_64Bit_Nov10.ics"&gt;http://msdn.microsoft.com/chats/outlook_reminders/04_MC_64Bit_Nov10.ics&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I also answered questions in a couple of excellent 'WebCasts' hosted by Kang Su Gatlin, one of our project managers on the compiler, last week that people might be interested in.&amp;nbsp;&amp;nbsp;&amp;nbsp;If I ever find the stinking links to them, I'll put them up here, too.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=254180" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item><item><title>First Post - all things x64</title><link>http://blogs.msdn.com/freik/archive/2004/11/05/252974.aspx</link><pubDate>Fri, 05 Nov 2004 23:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:252974</guid><dc:creator>Kevin Frei</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/freik/comments/252974.aspx</comments><wfw:commentRss>http://blogs.msdn.com/freik/commentrss.aspx?PostID=252974</wfw:commentRss><wfw:comment>http://blogs.msdn.com/freik/rsscomments.aspx?PostID=252974</wfw:comment><description>&lt;DIV&gt;Welcome to my stinkin' blog.&amp;nbsp; I just wanted a place to dump interesting &amp;amp; useful blobs of information about what I've been doing for the past&amp;nbsp;4 or 5&amp;nbsp;years of my life @ work:&amp;nbsp; x64.&lt;/DIV&gt;
&lt;DIV&gt;My name is Kevin Frei, and I've been a developer on the x64 (aka AMD64, EM64T, and x86-64) compiler since it's inception.&amp;nbsp; I'm originally from Pocatello, ID, I really don't miss it one bit.&amp;nbsp; Except maybe the cost of housing :-)&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;So, here's the stuff I wanted to make public.&amp;nbsp; It's all generally about how to successfully use Windows XP Pro for x64 (and Win2003 Server for x64) in a normal day-to-day environment.&amp;nbsp; I'll probably toss out useful compiler/code gen things in the future, but for right now, this is it:&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;So, without further ado, here we go:&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;%windir%\syswow64\cmd.exe&lt;/SPAN&gt; is your best friend&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;When you launch the 32 bit command prompt, &lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;PROCESSOR_ARCHITECTURE&lt;/SPAN&gt; is set to &lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;x86&lt;/SPAN&gt;, &lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;ProgramFiles&lt;/SPAN&gt; is set to "&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;c:\program files (x86)&lt;/SPAN&gt;", and suddenly lots of things 'just work'&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Use Internet Explorer (32 bit)&lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;The 64 bit internet explorer works great, unless you need to run activeX controls, which are present on far too many web pages out there. Of course, the 64 bit version of IE is kind of nice, simply because there's no more irritating Flash advertisements, and no obnoxious addins.&amp;nbsp; I've actually started using Avant Browser, and have found that it's quite pleasant, though always 32 bit...&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;'Program Files (x86)' can cause lots of problems with scripts&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;If you have scripts that use &lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;%ProgramFiles%,&lt;/SPAN&gt; this can act a little weird, due to parentheses parsing problems. You can work your way around it by doing this from inside your script:&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=2&gt;for %%D in ("%ProgramFiles%") do set ProgramFiles=%%~sD&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;This makes the variable use short pathnames: no more parenthese or spaces. It's actually a useful trick in general to get spaces &amp;amp; parentheses out of environment variables, in general.&amp;nbsp; Maybe I'll fix mine fixer script and put it up here in the future...&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Detecting that you're running under WOW64 from 32 bit scripts&lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;PROCESSOR_ARCHITEW6432 is set to the real processor architecture when you're running syswow64\cmd.exe&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;When is system32 not system32?&lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;DIV&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;When it's been mapped to syswow64! If you're running under WoW64, your actual system32 directory isn't visible - it's a duplicate of syswow64. Magic! Sometimes this can be little confusing, though.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;
&lt;UL&gt;
&lt;LI&gt;How can I see stuff in the real system32 from a 32 bit process?&lt;o:p&gt;&lt;/o:p&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;From a 64 bit CMD, linkd [somewhere] %windir%\system32&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Now, from 32 bit apps, you can see the contents of the real system32 [with all it’s 64 bit images] from a 32 bit process, from the [somewhere] directory.&amp;nbsp; I don't know if linkd.exe is available outside of MSFT.&amp;nbsp; I'm sure there's some other way to accomplish this...&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=252974" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx">Developer Info</category></item></channel></rss>