<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">FreiK's WebLog</title><subtitle type="html">AMD64 (aka X64) Stuff - Random warblings of a 64 bit Windows junkie</subtitle><id>http://blogs.msdn.com/freik/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/freik/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2006-07-20T13:22:00Z</updated><entry><title>Quick note about x64 Tail call</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2009/02/09/quick-note-about-x64-tail-call.aspx" /><id>http://blogs.msdn.com/freik/archive/2009/02/09/quick-note-about-x64-tail-call.aspx</id><published>2009-02-09T22:28:43Z</published><updated>2009-02-09T22:28:43Z</updated><content type="html">A coworker on the CLR dropped by recently, having hit a brick wall about some problem he was having with some ASM code for x64 that was trying to tail call.&amp;#160; He has already grep’ed through the ABI docs, and had actually hit this blog prior to knocking on my door.&amp;#160; The problem?&amp;#160; How to emit a tail call through a register such that the OS unwinder doesn’t puke. The quick answer is to use a REX prefix extension on the JMP instruction.&amp;#160; For those of you that know what you’re doing,...(&lt;a href="http://blogs.msdn.com/freik/archive/2009/02/09/quick-note-about-x64-tail-call.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9409160" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>What's in a title?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2008/06/03/what-s-in-a-title.aspx" /><id>http://blogs.msdn.com/freik/archive/2008/06/03/what-s-in-a-title.aspx</id><published>2008-06-03T23:50:00Z</published><updated>2008-06-03T23:50:00Z</updated><content type="html">My wife just asked "What's an 'after-sales engineer'?" I parsed the terms, and came up with "Tech Support Dude". As a teenager, I was a Foliage Architect (I mowed lawns), System Builder (computer assembly slave), Network Administrator (very poorly paid, local 'after sales engineer') and an Information Delivery Engineer (paper boy)....(&lt;a href="http://blogs.msdn.com/freik/archive/2008/06/03/what-s-in-a-title.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8572133" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>The customer is wrong</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2008/04/02/the-customer-is-wrong.aspx" /><id>http://blogs.msdn.com/freik/archive/2008/04/02/the-customer-is-wrong.aspx</id><published>2008-04-03T07:45:45Z</published><updated>2008-04-03T07:45:45Z</updated><content type="html">I just watched the highly lame &amp;#8220;You wouldn&amp;#8217;t steal a car&amp;#8230;Downloading pirated movies is stealing &amp;#8221; &amp;#8216;trailer&amp;#8217;. How&amp;#8217;s this for irony: I watched this trailer because it was the SECOND thing to play on the DVD of Die Hard 4 that I just purchased. The FIRST thing to play on this DVD was a menu that asked me what language I would like: English, Mandarin, Russian, and about 8 other languages that I had never heard of, or couldn&amp;#8217;t read. The DVD cost me 7RMB...(&lt;a href="http://blogs.msdn.com/freik/archive/2008/04/02/the-customer-is-wrong.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8353065" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>Turning off comments for a while...</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2008/02/18/turning-off-comments-for-a-while.aspx" /><id>http://blogs.msdn.com/freik/archive/2008/02/18/turning-off-comments-for-a-while.aspx</id><published>2008-02-18T22:31:00Z</published><updated>2008-02-18T22:31:00Z</updated><content type="html">The spam bots have been causing me all sorts of trouble - I had over 1000 messages informing me that some spam has been deleted over the weekend. I'm going to kill comments, and hope that in a few months, (after I get a chance to write up something of value), the spam bots will have stopped attempting to comment on my blog. In the mean time, if you want to ask me a question, my email address is the title of my blog [freik] except my first initial comes _before_ my last name] at m1cr0s0ft.c0m, except...(&lt;a href="http://blogs.msdn.com/freik/archive/2008/02/18/turning-off-comments-for-a-while.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7797072" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>Vista x64 Media Center 'fix'</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2007/09/07/vista-x64-media-center-fix.aspx" /><id>http://blogs.msdn.com/freik/archive/2007/09/07/vista-x64-media-center-fix.aspx</id><published>2007-09-07T19:52:00Z</published><updated>2007-09-07T19:52:00Z</updated><content type="html">&amp;lt;RETRACTION&amp;gt; Crap. After getting a couple of comments saying they tried the same thing, and it didn't work for them, I went back and tried it myself. And it turns out it doesn't work. I think I had tried it with some media that I had already transcoded to WMV without realizing it. The reason it doesn't work is actually quite simple: The managed assemblies aren't pure IL - they're IJW images (lame-speak for "they contain some native code") so they're hard-tied to the platform they're shipped...(&lt;a href="http://blogs.msdn.com/freik/archive/2007/09/07/vista-x64-media-center-fix.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4813026" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>How not to benchmark different languages</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2007/06/11/how-not-to-benchmark-different-languages.aspx" /><id>http://blogs.msdn.com/freik/archive/2007/06/11/how-not-to-benchmark-different-languages.aspx</id><published>2007-06-11T22:41:00Z</published><updated>2007-06-11T22:41:00Z</updated><content type="html">&lt;P&gt;I've recently been trolling the web for any sort of language-comparision benchmarks, to see how the CLR's JIT stacks up to the competition.&amp;nbsp; Dr. Dobbs has what seemed to be a pretty reasonable &lt;A class="" href="http://www.ddj.com/dept/cpp/184401976" target=_blank mce_href="http://www.ddj.com/dept/cpp/184401976"&gt;micro-benchmark article&lt;/A&gt;.&amp;nbsp; It's not particularly insightful, but hey, it is hard to come up with stuff that makes sense to compare across multiple disparate languages.&amp;nbsp; I started looking for specific C# to Java comparisons and came upon this little &lt;A class="" href="http://www.javaperformancetuning.com/news/qotm028.shtml" target=_blank mce_href="http://www.javaperformancetuning.com/news/qotm028.shtml"&gt;gem&lt;/A&gt;.&amp;nbsp; I'll give you a few minutes to read it.&lt;/P&gt;
&lt;P&gt;Now that you've read it, I would like to challenge you to understand how anyone would ever believe the question of "How long does it take to do nothing 1 billion times" in any language is worth comparing.&amp;nbsp; Seriously, ignore the thoughts regarding whether the comparison itself was fair or not.&amp;nbsp; The best part of that article is that the Java JIT they seem to be pushing doesn't get rid of the empty loops in a newer version.&amp;nbsp;&amp;nbsp;Then look at their 'testing methodology' (or the lack thereof).&amp;nbsp; Not only are they not actually benchmarking anything that anyone with a brain in their head would care about, but they didn't even bother to figure out how use the tools that they claim to be comparing against.&amp;nbsp; Does anyone that actually &lt;EM&gt;uses &lt;/EM&gt;C++* think that if they care about performance they're not going to enable the optimizer?&amp;nbsp; Every reasonable C++ compiler on the planet will completely eliminate the loops if only told to optimize.&amp;nbsp; And then the comparison against Assembly stuck in my craw.&amp;nbsp; Assembly is there because you KNOW WHAT YOU'RE DOING!!!!&amp;nbsp; If an assembly programmer writes a loop that iterates for a billion times, it's probably because they're trying to measure some particular pattern of code on the CPU they're running.&lt;/P&gt;
&lt;P&gt;So (still snickering at the previous stuff), I guess I'm asking for input:&amp;nbsp; Does anyone have any non-micro-benchmark relatively objective managed code comparison links they'd recommend?&amp;nbsp; I'd really like to see how the CLR's JIT stacks up against some of the JVM's out there, for more than just little tiny toy code samples.&lt;/P&gt;
&lt;P&gt;I'm also interested in 'end-to-end' timing, which includes JIT time.&amp;nbsp; Microbenchmarks with internal clocks don't tell you how long something actually ran for.&amp;nbsp; If a JIT takes 5 minutes to figure out it can remove 2 dead loops, your runtime isn't less than 1 second - it's less than 5 minutes and 1 second.&lt;/P&gt;
&lt;P&gt;-Kev&lt;/P&gt;
&lt;P&gt;* I found 4 different syntax errors in the C++ source code they provided...&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3235571" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>Boost 1.34.0 and how to get it to build for AMD64...</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2007/06/07/boost-1-34-0-and-how-to-get-it-to-build-for-amd64.aspx" /><id>http://blogs.msdn.com/freik/archive/2007/06/07/boost-1-34-0-and-how-to-get-it-to-build-for-amd64.aspx</id><published>2007-06-08T06:37:00Z</published><updated>2007-06-08T06:37:00Z</updated><content type="html">&lt;P&gt;I've recently been deluged by a pile of new electronic gadgets* so that I haven't had time to do much coding.&amp;nbsp; So I was looking around yesterday and found that there's (finally) a new version of Boost available.&amp;nbsp; I was actually underwhelmed by the lack of interesting new libraries that have been added (there have been a number of interesting libraries approved, but the only one of the group that have been approved that I was anxious to use trivially was Xpressive - I might rip out "for each" from my source code to try BOOST_FOREACH instead, too).&amp;nbsp; That aside, I immediately discovered that they removed support for BJam V1, and require BJam V2.&amp;nbsp; It took me another 2 hours of digging to figure out how to build the 64 bit libraries with the new build system.&amp;nbsp; Here's how you do it:&lt;/P&gt;&lt;PRE&gt;bjam toolset=msvc address-model=64 stage&lt;/PRE&gt;
&lt;P&gt;And, voila - amd64 builds.&amp;nbsp; For the discerning multi-proc engineer (most of us are now, right?) try adding a -j%NUMBER_OF_PROCESSORS% to that command line to use every CPU core your machine has [it builds quite quickly on my Core 2 Quad, and my 2x2 Opteron [faster on my Opteron, actually - the C++ compiler eats data cache for breakfast - I think the extra pipe to memory really helps].&lt;/P&gt;
&lt;P&gt;And now, to explain the * above:&lt;/P&gt;
&lt;P&gt;Over the past&amp;nbsp;two or three months, I've splurged a lot on myself and/or my wife:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="" href="http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11035734" target=_blank mce_href="http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11035734"&gt;Sony HD-SR1 camcorder&lt;/A&gt; - Good video quality - shockingly better than my old JVC GZ-27, and significantly better than any of the MiniDV camcorders I've owned. &lt;A class="" href="http://en.wikipedia.org/wiki/AVCHD" target=_blank mce_href="http://en.wikipedia.org/wiki/AVCHD"&gt;AVCHD&lt;/A&gt; is less than a great post-processing experience, right now, though&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://www.apple.com/ipodshuffle/" target=_blank mce_href="http://www.apple.com/ipodshuffle/"&gt;Apple iPod Shuffle&lt;/A&gt; - Fabulous form factor, super-crappy &lt;A class="" href="http://www.apple.com/itunes/" target=_blank mce_href="http://www.apple.com/itunes/"&gt;software&lt;/A&gt; - one of the devs on my team said that I must be using it in a way that Steve Jobs doesn't, because that's the only way Apple tests their products.&amp;nbsp; I would have waited to get a &lt;A class="" href="http://us.creative.com/products/product.asp?category=213&amp;amp;subcategory=214&amp;amp;product=16424" target=_blank mce_href="http://us.creative.com/products/product.asp?category=213&amp;amp;subcategory=214&amp;amp;product=16424"&gt;Creative Labs Stone&lt;/A&gt; for half the price, but it was a gift for my wife for her birthday, and the Stone wasn't yet available.&amp;nbsp; Seriously, why do I need a $#@@ driver to use a %#@# flash device?&amp;nbsp; To be fair with my complaints, the Zune does the same thing.&amp;nbsp; Lame lame lame lame.&amp;nbsp; Everyone else on the planet calls 'em USB storage devices, what is wrong with Apple and Microsoft?&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://www.rokulabs.com/products_soundbridge.php" target=_blank mce_href="http://www.rokulabs.com/products_soundbridge.php"&gt;Roku SoundBridge M500&lt;/A&gt; - Great size, great audio quality, but it took forever for me to figure out that Windows Media Connect doesn't like to share audio files that are already on a network share.&amp;nbsp; Once I migrated my music onto my media center, it actually navigated my 150+ Gigs of audio remarkably well, and handles &lt;A class="" href="http://blogs.msdn.com/freik/archive/2005/09/27/474625.aspx" target=_blank mce_href="http://blogs.msdn.com/freik/archive/2005/09/27/474625.aspx"&gt;lossless WMA &lt;/A&gt;like a champ!&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" title="Bose Companion 2 Speakers" href="http://www.bose.com/controller?event=VIEW_PRODUCT_PAGE_EVENT&amp;amp;product=companion2_multimedia_index" target=_blank mce_href="http://www.bose.com/controller?event=VIEW_PRODUCT_PAGE_EVENT&amp;amp;product=companion2_multimedia_index"&gt;Bose Companion 2 speakers&lt;/A&gt; - Fabulous audio quality, nice looking desing - attached to the SoundBridge in our master bathroom - All my wife needs now is a hot plate and she could live in the master bathroom&lt;/LI&gt;
&lt;LI&gt;Final not-so-electronic not-so-gadget:&amp;nbsp; &lt;A class="" href="http://www.ellsworthbikes.com/bikes/epiphany/default.aspx" target=_blank mce_href="http://www.ellsworthbikes.com/bikes/epiphany/default.aspx"&gt;Ellsworth Epiphany&lt;/A&gt; mountain bike, built up with most SRAM X.9 components.&amp;nbsp; This thing climbs better than my 1997 GT aluminum hard tail.&amp;nbsp; It's much bigger than my GT, but weighs about the same, and I have no idea what I'll do with those 27 gears.&amp;nbsp; I think I only ever used 19 of the 21 available on my GT.&amp;nbsp; I picked it up on Monday night at REI [wouldn't have bought it except for their nice little test track demonstrated that it really does have &lt;A class="" href="http://www.mtbr.com/reviews/Allmtn_Full_Suspension/product_125675.shtml" target=_blank mce_href="http://www.mtbr.com/reviews/Allmtn_Full_Suspension/product_125675.shtml"&gt;no weaknesses&lt;/A&gt;], I've ridden it to work 2 days [in the rain, but I really didn't care], and I'll be riding it this weekend (probably in the mud) Saturday and Sunday morning.&amp;nbsp; &lt;A class="" href="http://www.bbtc.org/trails/show_trail.php?location_id=2" target=_blank mce_href="http://www.bbtc.org/trails/show_trail.php?location_id=2"&gt;St. Edwards park&lt;/A&gt;, and perhaps I'll go visit the &lt;A class="" href="http://www.bbtc.org/trails/show_trail.php?location_id=37" target=_blank mce_href="http://www.bbtc.org/trails/show_trail.php?location_id=37"&gt;Tape Worm&lt;/A&gt; in Renton.&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3154815" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry><entry><title>How to use RtlUnwindEx</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2007/03/15/how-to-use-rtlunwindex.aspx" /><id>http://blogs.msdn.com/freik/archive/2007/03/15/how-to-use-rtlunwindex.aspx</id><published>2007-03-15T18:24:00Z</published><updated>2007-03-15T18:24:00Z</updated><content type="html">&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;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Developer Info" scheme="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx" /><category term="Bugs" scheme="http://blogs.msdn.com/freik/archive/tags/Bugs/default.aspx" /></entry><entry><title>AMD64 unwind info gotchas</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2007/03/12/amd64-unwind-info-gotchas.aspx" /><id>http://blogs.msdn.com/freik/archive/2007/03/12/amd64-unwind-info-gotchas.aspx</id><published>2007-03-12T20:34:00Z</published><updated>2007-03-12T20:34:00Z</updated><content type="html">&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;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Developer Info" scheme="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx" /><category term="X64 ABI Info" scheme="http://blogs.msdn.com/freik/archive/tags/X64+ABI+Info/default.aspx" /></entry><entry><title>New Job, SP1</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2006/12/19/new-job-sp1.aspx" /><id>http://blogs.msdn.com/freik/archive/2006/12/19/new-job-sp1.aspx</id><published>2006-12-19T20:42:00Z</published><updated>2006-12-19T20:42:00Z</updated><content type="html">&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;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Developer Info" scheme="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx" /></entry><entry><title>Speaking in 'public'...</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2006/10/17/speaking-in-public.aspx" /><id>http://blogs.msdn.com/freik/archive/2006/10/17/speaking-in-public.aspx</id><published>2006-10-18T06:35:00Z</published><updated>2006-10-18T06:35:00Z</updated><content type="html">&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;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Developer Info" scheme="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx" /><category term="X64 ABI Info" scheme="http://blogs.msdn.com/freik/archive/tags/X64+ABI+Info/default.aspx" /></entry><entry><title>Bug in x86 inline assembly to watch out for</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2006/10/17/bug-in-x86-inline-assembly-to-watch-out-for.aspx" /><id>http://blogs.msdn.com/freik/archive/2006/10/17/bug-in-x86-inline-assembly-to-watch-out-for.aspx</id><published>2006-10-17T23:53:00Z</published><updated>2006-10-17T23:53:00Z</updated><content type="html">&lt;P&gt;Imagine this very lame code:&lt;/P&gt;&lt;PRE&gt;int main() {}

void BugAsm() 
{
   __asm {
        MOV     [ESP+12],OFFSET main
   }
}

void(*BugAsmPt)()=&amp;amp;BugAsm; // this is just to make sure the function is not removed by /OPT:REF

&lt;/PRE&gt;
&lt;P&gt;Now imagine your significantly less lame code doing something similar.&lt;BR&gt;Now imagine that the compiler crashes with a bizzare message about "x86\code.c" something or other.&lt;/P&gt;
&lt;P&gt;Well, you can fix this problem by changing the assembly code to this:&lt;/P&gt;
&lt;P&gt;mov DWORD PTR[esp+12], OFFSET main&lt;/P&gt;
&lt;P&gt;Another unfixed bug, worked around :-|&lt;/P&gt;
&lt;P&gt;-Kev&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=836118" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Bugs" scheme="http://blogs.msdn.com/freik/archive/tags/Bugs/default.aspx" /></entry><entry><title>A more flexible array template [and the evolution of the idea]</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2006/09/18/a-more-flexible-array-template-and-the-evolution-of-the-idea.aspx" /><id>http://blogs.msdn.com/freik/archive/2006/09/18/a-more-flexible-array-template-and-the-evolution-of-the-idea.aspx</id><published>2006-09-19T00:17:00Z</published><updated>2006-09-19T00:17:00Z</updated><content type="html">&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;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Developer Info" scheme="http://blogs.msdn.com/freik/archive/tags/Developer+Info/default.aspx" /></entry><entry><title>ML64 bug to watch out for</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2006/07/20/673120.aspx" /><id>http://blogs.msdn.com/freik/archive/2006/07/20/673120.aspx</id><published>2006-07-20T23:45:00Z</published><updated>2006-07-20T23:45:00Z</updated><content type="html">If you're porting your application to x64, and you use much in the way of __asm in your x86 code, you're likely to start looking at ml64 - the 64 bit version of Masm.&amp;nbsp; The reason you're likely to do this is that the x64 compiler doesn't support __asm blocks in C code.&amp;nbsp; So you can either use the compiler intrinsic functions [and there are a lot of 'em, and they're all documented relatively well], or you have to use ml64.&amp;nbsp; For folks that aren't new to Masm, you're also likely to try to use some of the nifty little time-saver features of Masm to automatically generate prologue's and epilogues for your functions.&amp;nbsp; For ML64, DO NOT DO THIS!&lt;br&gt;Here's an example:&lt;br&gt;&lt;font face="Courier New"&gt;.DATA&lt;br&gt;.CODE&lt;br&gt;testfunc PROC uses rbx&lt;br&gt;xor rbx, rbx&lt;br&gt;ret&lt;br&gt;testfunc ENDP&lt;br&gt;END&lt;br&gt;&lt;font face="Times New Roman"&gt;There are 2 problems with the code that ML64 generates.&amp;nbsp; #1:&amp;nbsp; There is no .xdata of any sort.&amp;nbsp; No unwind directives are emitted, despite the fact that you're allocating stack, and saving a nonvolatile register.&amp;nbsp; #2:&amp;nbsp; The epilogue is invalid - it uses the 'leave' instruction, which is ineffecient, but also just plain illegal in an x64 function epilogue.&amp;nbsp; The stack unwind routines will not properly recognize the instruction sequence as an epilogue, so the debugger and the EH routines will all fail [the EH routines will just terminate your process if an exception occurs while testfunc is on the stack].&lt;br&gt;&lt;br&gt;BTW - Here's the &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101239"&gt;link&lt;/a&gt; to the customer bug.&amp;nbsp; It came in about 3 months too soon for serious consideration for VC8, so we punted it to the next version, but now it's pushed out until we get some more resources for investment in MASM.&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=673120" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author><category term="Bugs" scheme="http://blogs.msdn.com/freik/archive/tags/Bugs/default.aspx" /></entry><entry><title>Visual C++ Code Gen &amp; Tools bugs</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/freik/archive/2006/07/20/673115.aspx" /><id>http://blogs.msdn.com/freik/archive/2006/07/20/673115.aspx</id><published>2006-07-20T23:22:00Z</published><updated>2006-07-20T23:22:00Z</updated><content type="html">My role for the past 6 months (and the next several) I'm charged with effectively "going down with the ship" WRT the current generation of code gen &amp;amp; tools for Visual C++.&amp;nbsp; This includes the linker, Masm, ml64, DIA, c2, pdb, and a few other miscellaneous components.&amp;nbsp; The entire ball of wax is to be replaced with components from a product with the much overused codename of Phoenix over the next few product cycles.&amp;nbsp; I have a skeleton crew [trust me on this one] to do the work, and I get to manage them.&amp;nbsp; As the lead of the bunch, I wind up making many less than pleasant calls of 'won't fix'ing a bugs that, in a previous product cycle, would have been fixed in a heart-beat.&amp;nbsp; I'm going to start blogging about each &amp;amp; every customer bug that I mark as "Won't Fix" simply to keep a public list of what not to do until the toolset is replaced.&lt;br&gt;I'm not sure how acceptable this is, but unless my management smacks me, I'm going to keep doing this for the next many months.&amp;nbsp; The next entry is the first of many...&lt;br&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=673115" width="1" height="1"&gt;</content><author><name>FreiK</name><uri>http://blogs.msdn.com/members/FreiK.aspx</uri></author></entry></feed>