<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-3138926820109616470</atom:id><lastBuildDate>Thu, 12 Nov 2009 14:18:58 +0000</lastBuildDate><title>Death Star Playset</title><description>My blog for technical notes.</description><link>http://www.mountainwerks.org/deathstarplayset/</link><managingEditor>noreply@blogger.com (Michael Stanton)</managingEditor><generator>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-1089681757012612809</guid><pubDate>Thu, 12 Nov 2009 08:42:00 +0000</pubDate><atom:updated>2009-11-12T06:18:58.243-08:00</atom:updated><title>Fixed used with anonymous delegates is tricky</title><description>I'm back (5 minutes later) to continue trying to understand a mystery with &lt;b&gt;fixed&lt;/b&gt;. At work our problem didn't just involve fixed(), but also the usage of fixed pointers inside an anonymous delegate &lt;b&gt;defined and called&lt;/b&gt; within the scope of the fixed block.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.andreaskahler.com/"&gt;Andreas&lt;/a&gt; came up with a nice test that surprised us both when we saw the disassembly. Here is the code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private delegate void Action();&lt;br /&gt;private unsafe void FixedIsColdComfortToDelegates(int runNumber)&lt;br /&gt;{&lt;br /&gt;    byte[] array = new byte[1];&lt;br /&gt;    fixed(byte *p = array)&lt;br /&gt;    {&lt;br /&gt;        Action action = () =&gt; { *p = 22; };&lt;br /&gt;        Thread.Sleep(10);&lt;br /&gt;        action();&lt;br /&gt;    }&lt;br /&gt;    if(22 != array[0])&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine("Experienced failure, run {0}!", runNumber);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The disassembly was interesting, basically the fixed() statement was ignored! The question is why. Ultimately I found out the bug:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;You can cause a fixed statement to be ignored by the JIT compiler if you simply include an anonymous delegate in the fixed block which references the fixed pointer. There is no need to run the delegate. Any additional usages of the fixed pointer in the fixed block will not prevent the fixed block from being ignored.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Here is my test program:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Threading;&lt;br /&gt;&lt;br /&gt;namespace FixedTest&lt;br /&gt;{&lt;br /&gt;    class FixedProblem&lt;br /&gt;    {    &lt;br /&gt;        private unsafe void Changer(byte *p)&lt;br /&gt;        {&lt;br /&gt;            // Do some allocations&lt;br /&gt;            byte[] bigarray = new byte[1024*50];&lt;br /&gt;            bigarray[3] = 34;&lt;br /&gt;            GC.Collect();&lt;br /&gt;            *p = bigarray[3];            &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private unsafe void NormalFixedStatement(int runNumber)&lt;br /&gt;        {            &lt;br /&gt;            byte[] array = new byte[100];            &lt;br /&gt;            fixed(byte *p = array)&lt;br /&gt;            {&lt;br /&gt;                Changer(p + 1); // will change array[1] to 34&lt;br /&gt;                Thread.Sleep(10);&lt;br /&gt;                *p = 10;            &lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            if(array[1] != 34)&lt;br /&gt;            {&lt;br /&gt;                Console.WriteLine("Experienced failure, run {0}", runNumber);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private unsafe void NullifiedFixedStatement(int runNumber)&lt;br /&gt;        {            &lt;br /&gt;            byte[] array = new byte[100];&lt;br /&gt;            fixed (byte* p = array)&lt;br /&gt;            {                                &lt;br /&gt;                Action action = () =&gt; { *p = 10; }; // This destroys the fixed statement&lt;br /&gt;                Changer(p + 1); // will change array[1] to 34&lt;br /&gt;                Thread.Sleep(10);&lt;br /&gt;                *p = 10; // but p isn't fixed!&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            if (array[1] != 34)&lt;br /&gt;            {&lt;br /&gt;                Console.WriteLine("Experienced failure, run {0}", runNumber);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        static void Main(string[] args)&lt;br /&gt;        {&lt;br /&gt;            FixedProblem p = new FixedProblem();&lt;br /&gt;            &lt;br /&gt;            int count = 500;&lt;br /&gt;&lt;br /&gt;            Console.WriteLine("First run a function with a fixed statement and no anonymous delegate that uses the fixed pointer");&lt;br /&gt;            for (int i = 0; i &lt; count; i++)&lt;br /&gt;            {&lt;br /&gt;                p.NormalFixedStatement(i);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            Console.WriteLine("Now run a function with a fixed statement and an anonymous delegate that uses the fixed pointer");&lt;br /&gt;            for (int i = 0; i &lt; count; i++)&lt;br /&gt;            {&lt;br /&gt;                p.NullifiedFixedStatement(i);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here is the output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;C:\FixedTest\bin\Release&gt;fixedtest.exe&lt;br /&gt;First run a function with a fixed statement and no anonymous delegate &lt;br /&gt;that uses the fixed pointer.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now run a function with a fixed statement and an anonymous delegate that &lt;br /&gt;uses the fixed pointer.&lt;br /&gt;&lt;br /&gt;Experienced failure, run 4&lt;br /&gt;Experienced failure, run 8&lt;br /&gt;Experienced failure, run 12&lt;br /&gt;Experienced failure, run 16&lt;br /&gt;Experienced failure, run 20&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I wonder if the CLR team knows about this bug? &lt;br /&gt;&lt;br /&gt;Update: My friend Josef points out that if you introduce a temporary variable and pass that in to the anonymous delegate then fixed protection is restored. Something like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;...&lt;br /&gt;byte *pTemp = p;&lt;br /&gt;Action action = () =&gt; { *pTemp = 10; }&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-1089681757012612809?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/11/fixed-used-with-anonymous-delegates-is.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-7067966867409290214</guid><pubDate>Thu, 12 Nov 2009 07:46:00 +0000</pubDate><atom:updated>2009-11-12T00:22:11.681-08:00</atom:updated><title>Fixed statement not what you expect (or is it?)</title><description>Recently we ran into the problem at work that a &lt;b&gt;fixed&lt;/b&gt; statement doesn't have the lifetime you expect. Consider:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;...&lt;br /&gt;fixed(byte *p = byteArray)&lt;br /&gt;{&lt;br /&gt;    UnmanagedCode(p);&lt;br /&gt;    OtherStuff();&lt;br /&gt;    Console.WriteLine("finished");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You might expect that p is held fixed until after the Console.WriteLine statement, but it's only held fixed &lt;b&gt;to the last usage of p&lt;/b&gt;, so the fixed protection terminates at the start of the &lt;b&gt;OtherStuff()&lt;/b&gt; line. This is something I used to know as a CLR dev, but since forgot. Do you want to see proof? Let's break out SOS.&lt;br /&gt;&lt;br /&gt;Here is a little test function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private unsafe void FixedToLastUsage() {&lt;br /&gt;    DebugBreak();&lt;br /&gt;&lt;br /&gt;    int size = 100;&lt;br /&gt;    byte[] byteArray = new byte[size];&lt;br /&gt;    byteArray[0] = 1;&lt;br /&gt;&lt;br /&gt;    fixed(byte *p = byteArray) {&lt;br /&gt;        Console.WriteLine("p = " + *p);&lt;br /&gt;        byte* p2 = p + 1;&lt;br /&gt;&lt;br /&gt;        // Now we won't reference p anymore but we'll do some other stuff.&lt;br /&gt;        // A look at the gc encoding should prove that p isn't protected beyond this point.&lt;br /&gt;        int sum = 0;&lt;br /&gt;        for(int i=0;i&lt;10;i++) {&lt;br /&gt;            sum += i;&lt;br /&gt;        }&lt;br /&gt;        Console.WriteLine("sum = " + sum.ToString());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The DebugBreak() is a pinvoke call to the Windows DebugBreak() function. This is just to make it easier for me to disassemble the function and use SOS in the Windows Debugger.&lt;br /&gt;&lt;br /&gt;Here is the disassembly of the method:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;0:000&gt; .loadby mscorwks sos&lt;br /&gt;0:000&gt; !clrstack&lt;br /&gt;OS Thread Id: 0xfe8 (0)&lt;br /&gt;ESP       EIP     &lt;br /&gt;0012f410 7c90120e [NDirectMethodFrameStandalone: 0012f410] FixedTest.Program.DebugBreak()&lt;br /&gt;0012f420 00d3014d FixedTest.Program.FixedToLastUsage()&lt;br /&gt;0012f474 00d300b4 FixedTest.Program.Main(System.String[])&lt;br /&gt;0012f69c 79e71b4c [GCFrame: 0012f69c] &lt;br /&gt;0:000&gt; !u d3014d&lt;br /&gt;Normal JIT generated code&lt;br /&gt;FixedTest.Program.FixedToLastUsage()&lt;br /&gt;Begin 00d30108, size 159&lt;br /&gt;00d30108 55              push    ebp&lt;br /&gt;00d30109 8bec            mov     ebp,esp&lt;br /&gt;00d3010b 83ec4c          sub     esp,4Ch&lt;br /&gt;00d3010e 33c0            xor     eax,eax&lt;br /&gt;00d30110 8945f4          mov     dword ptr [ebp-0Ch],eax&lt;br /&gt;00d30113 8945ec          mov     dword ptr [ebp-14h],eax&lt;br /&gt;00d30116 894dfc          mov     dword ptr [ebp-4],ecx&lt;br /&gt;00d30119 833de430930000  cmp     dword ptr ds:[9330E4h],0&lt;br /&gt;00d30120 7405            je      00d30127&lt;br /&gt;00d30122 e89aa53979      call    mscorwks!JIT_DbgIsJustMyCode (7a0ca6c1)&lt;br /&gt;00d30127 33d2            xor     edx,edx&lt;br /&gt;00d30129 8955d4          mov     dword ptr [ebp-2Ch],edx&lt;br /&gt;00d3012c 33d2            xor     edx,edx&lt;br /&gt;00d3012e 8955e8          mov     dword ptr [ebp-18h],edx&lt;br /&gt;00d30131 33d2            xor     edx,edx&lt;br /&gt;00d30133 8955d8          mov     dword ptr [ebp-28h],edx&lt;br /&gt;00d30136 33d2            xor     edx,edx&lt;br /&gt;00d30138 8955f8          mov     dword ptr [ebp-8],edx&lt;br /&gt;00d3013b c745e400000000  mov     dword ptr [ebp-1Ch],0&lt;br /&gt;00d30142 33d2            xor     edx,edx&lt;br /&gt;00d30144 8955f0          mov     dword ptr [ebp-10h],edx&lt;br /&gt;00d30147 90              nop&lt;br /&gt;00d30148 e8ffbec0ff      call    0093c04c (FixedTest.Program.DebugBreak(), mdToken: 06000001)&lt;br /&gt;&gt;&gt;&gt; 00d3014d 90              nop&lt;br /&gt;00d3014e c745f864000000  mov     dword ptr [ebp-8],64h&lt;br /&gt;00d30155 8b55f8          mov     edx,dword ptr [ebp-8]&lt;br /&gt;00d30158 b902410c79      mov     ecx,offset mscorlib_ni+0x4102 (790c4102)&lt;br /&gt;00d3015d e83620bfff      call    00922198 (JitHelp: CORINFO_HELP_NEWARR_1_VC)&lt;br /&gt;00d30162 8945d0          mov     dword ptr [ebp-30h],eax&lt;br /&gt;00d30165 8b45d0          mov     eax,dword ptr [ebp-30h]&lt;br /&gt;00d30168 8945d8          mov     dword ptr [ebp-28h],eax&lt;br /&gt;00d3016b 8b45d8          mov     eax,dword ptr [ebp-28h]&lt;br /&gt;00d3016e 83780400        cmp     dword ptr [eax+4],0&lt;br /&gt;00d30172 7705            ja      00d30179&lt;br /&gt;00d30174 e883c13979      call    mscorwks!JIT_RngChkFail (7a0cc2fc)&lt;br /&gt;00d30179 c6400801        mov     byte ptr [eax+8],1&lt;br /&gt;00d3017d 8b45d8          mov     eax,dword ptr [ebp-28h]&lt;br /&gt;00d30180 8945d4          mov     dword ptr [ebp-2Ch],eax&lt;br /&gt;00d30183 837dd400        cmp     dword ptr [ebp-2Ch],0&lt;br /&gt;00d30187 7409            je      00d30192&lt;br /&gt;00d30189 8b45d4          mov     eax,dword ptr [ebp-2Ch]&lt;br /&gt;00d3018c 83780400        cmp     dword ptr [eax+4],0&lt;br /&gt;00d30190 7508            jne     00d3019a&lt;br /&gt;00d30192 33d2            xor     edx,edx&lt;br /&gt;00d30194 8955f4          mov     dword ptr [ebp-0Ch],edx&lt;br /&gt;00d30197 90              nop&lt;br /&gt;00d30198 eb14            jmp     00d301ae&lt;br /&gt;00d3019a 8b45d4          mov     eax,dword ptr [ebp-2Ch]&lt;br /&gt;00d3019d 83780400        cmp     dword ptr [eax+4],0&lt;br /&gt;00d301a1 7705            ja      00d301a8&lt;br /&gt;00d301a3 e854c13979      call    mscorwks!JIT_RngChkFail (7a0cc2fc)&lt;br /&gt;00d301a8 8d4008          lea     eax,[eax+8]&lt;br /&gt;00d301ab 8945f4          mov     dword ptr [ebp-0Ch],eax&lt;br /&gt;00d301ae 90              nop&lt;br /&gt;00d301af b920353379      mov     ecx,offset mscorlib_ni+0x273520 (79333520) (MT: System.Byte)&lt;br /&gt;00d301b4 e8631ebfff      call    0092201c (JitHelp: CORINFO_HELP_NEWSFAST)&lt;br /&gt;00d301b9 8945cc          mov     dword ptr [ebp-34h],eax&lt;br /&gt;00d301bc 8b0530202a02    mov     eax,dword ptr ds:[22A2030h] ("p = ")&lt;br /&gt;00d301c2 8945b8          mov     dword ptr [ebp-48h],eax&lt;br /&gt;00d301c5 8b45cc          mov     eax,dword ptr [ebp-34h]&lt;br /&gt;00d301c8 8b55f4          mov     edx,dword ptr [ebp-0Ch]&lt;br /&gt;00d301cb 8955e0          mov     dword ptr [ebp-20h],edx&lt;br /&gt;00d301ce 8b55e0          mov     edx,dword ptr [ebp-20h]&lt;br /&gt;00d301d1 8a12            mov     dl,byte ptr [edx]&lt;br /&gt;00d301d3 885004          mov     byte ptr [eax+4],dl&lt;br /&gt;00d301d6 8b45cc          mov     eax,dword ptr [ebp-34h]&lt;br /&gt;00d301d9 8945b4          mov     dword ptr [ebp-4Ch],eax&lt;br /&gt;00d301dc 8b4db8          mov     ecx,dword ptr [ebp-48h]&lt;br /&gt;00d301df 8b55b4          mov     edx,dword ptr [ebp-4Ch]&lt;br /&gt;00d301e2 e869ca5978      call    mscorlib_ni+0x20cc50 (792ccc50) (System.String.Concat(System.Object, System.Object), mdToken: 060001c5)&lt;br /&gt;00d301e7 8945c8          mov     dword ptr [ebp-38h],eax&lt;br /&gt;00d301ea 8b4dc8          mov     ecx,dword ptr [ebp-38h]&lt;br /&gt;00d301ed e82637a678      call    mscorlib_ni+0x6d3918 (79793918) (System.Console.WriteLine(System.String), mdToken: 060007c8)&lt;br /&gt;00d301f2 90              nop&lt;br /&gt;00d301f3 8b45f4          mov     eax,dword ptr [ebp-0Ch]&lt;br /&gt;00d301f6 8945dc          mov     dword ptr [ebp-24h],eax&lt;br /&gt;00d301f9 8b45dc          mov     eax,dword ptr [ebp-24h]&lt;br /&gt;00d301fc 40              inc     eax&lt;br /&gt;00d301fd 8945f0          mov     dword ptr [ebp-10h],eax&lt;br /&gt;00d30200 33d2            xor     edx,edx&lt;br /&gt;00d30202 8955ec          mov     dword ptr [ebp-14h],edx&lt;br /&gt;00d30205 33d2            xor     edx,edx&lt;br /&gt;00d30207 8955e8          mov     dword ptr [ebp-18h],edx&lt;br /&gt;00d3020a 90              nop&lt;br /&gt;00d3020b eb0b            jmp     00d30218&lt;br /&gt;00d3020d 90              nop&lt;br /&gt;00d3020e 8b45e8          mov     eax,dword ptr [ebp-18h]&lt;br /&gt;00d30211 0145ec          add     dword ptr [ebp-14h],eax&lt;br /&gt;00d30214 90              nop&lt;br /&gt;00d30215 ff45e8          inc     dword ptr [ebp-18h]&lt;br /&gt;00d30218 837de80a        cmp     dword ptr [ebp-18h],0Ah&lt;br /&gt;00d3021c 0f9cc0          setl    al&lt;br /&gt;00d3021f 0fb6c0          movzx   eax,al&lt;br /&gt;00d30222 8945e4          mov     dword ptr [ebp-1Ch],eax&lt;br /&gt;00d30225 837de400        cmp     dword ptr [ebp-1Ch],0&lt;br /&gt;00d30229 75e2            jne     00d3020d&lt;br /&gt;00d3022b 8b0534202a02    mov     eax,dword ptr ds:[22A2034h] ("sum = ")&lt;br /&gt;00d30231 8945c4          mov     dword ptr [ebp-3Ch],eax&lt;br /&gt;00d30234 8d4dec          lea     ecx,[ebp-14h]&lt;br /&gt;00d30237 e8d40a5b78      call    mscorlib_ni+0x220d10 (792e0d10) (System.Int32.ToString(), mdToken: 06000b22)&lt;br /&gt;00d3023c 8945c0          mov     dword ptr [ebp-40h],eax&lt;br /&gt;00d3023f 8b55c0          mov     edx,dword ptr [ebp-40h]&lt;br /&gt;00d30242 8b4dc4          mov     ecx,dword ptr [ebp-3Ch]&lt;br /&gt;00d30245 e806ea5478      call    mscorlib_ni+0x1bec50 (7927ec50) (System.String.Concat(System.String, System.String), mdToken: 060001c9)&lt;br /&gt;00d3024a 8945bc          mov     dword ptr [ebp-44h],eax&lt;br /&gt;00d3024d 8b4dbc          mov     ecx,dword ptr [ebp-44h]&lt;br /&gt;00d30250 e8c336a678      call    mscorlib_ni+0x6d3918 (79793918) (System.Console.WriteLine(System.String), mdToken: 060007c8)&lt;br /&gt;00d30255 90              nop&lt;br /&gt;00d30256 90              nop&lt;br /&gt;00d30257 33d2            xor     edx,edx&lt;br /&gt;00d30259 8955f4          mov     dword ptr [ebp-0Ch],edx&lt;br /&gt;00d3025c 90              nop&lt;br /&gt;00d3025d 8be5            mov     esp,ebp&lt;br /&gt;00d3025f 5d              pop     ebp&lt;br /&gt;00d30260 c3              ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here is the gc encoding for the method. What is gc encoding? I think the SOS help explains it best. (Depending on your feelings about SOS help you can thank or curse me...I wrote it over the Christmas holidays in 2002 or 2003, I forgot)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;0:000&gt; !help GCInfo&lt;br /&gt;-------------------------------------------------------------------------------&lt;br /&gt;!GCInfo (&lt;MethodDesc address&gt; | &lt;Code address&gt;)&lt;br /&gt;&lt;br /&gt;!GCInfo is especially useful for CLR Devs who are trying to determine if there &lt;br /&gt;is a bug in the JIT Compiler. It parses the GCEncoding for a method, which is a&lt;br /&gt;compressed stream of data indicating when registers or stack locations contain &lt;br /&gt;managed objects. It is important to keep track of this information, because if &lt;br /&gt;a garbage collection occurs, the collector needs to know where roots are so it &lt;br /&gt;can update them with new object pointer values.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You should copy this gc info into a notepad on a second monitor and read it as you read the disassembly. It becomes clear pretty quick that &lt;b&gt;EBP-0CH&lt;/b&gt; is our pointer &lt;b&gt;p&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;0:000&gt; !GCInfo d3014d&lt;br /&gt;entry point 00d30108&lt;br /&gt;Normal JIT generated code&lt;br /&gt;GC info 00931934&lt;br /&gt;Method info block:&lt;br /&gt;    method      size   = 0159&lt;br /&gt;    prolog      size   = 17 &lt;br /&gt;    epilog      size   =  4 &lt;br /&gt;    epilog     count   =  1 &lt;br /&gt;    epilog      end    = yes  &lt;br /&gt;    callee-saved regs  = EBP &lt;br /&gt;    ebp frame          = yes  &lt;br /&gt;    fully interruptible= yes  &lt;br /&gt;    double align       = no  &lt;br /&gt;    arguments size     =  0 DWORDs&lt;br /&gt;    stack frame size   = 19 DWORDs&lt;br /&gt;    untracked count    =  2 &lt;br /&gt;    var ptr tab count  = 10 &lt;br /&gt;    epilog        at   0155&lt;br /&gt;    argTabOffset = 22  &lt;br /&gt;82 59 D2 81 D3 | &lt;br /&gt;B9 93 F1 40 0A | &lt;br /&gt;22             | &lt;br /&gt;&lt;br /&gt;Pointer table:&lt;br /&gt;04             |             [EBP-04H] an untracked  local&lt;br /&gt;05             |             [EBP-0CH] an untracked pinned byref local&lt;br /&gt;2C 24 82 35    | 0024..0159  [EBP-2CH] a  pointer&lt;br /&gt;28 0A 82 2B    | 002E..0159  [EBP-28H] a  pointer&lt;br /&gt;30 2F 0F       | 005D..006C  [EBP-30H] a  pointer&lt;br /&gt;34 57 26       | 00B4..00DA  [EBP-34H] a  pointer&lt;br /&gt;48 09 1D       | 00BD..00DA  [EBP-48H] a  pointer&lt;br /&gt;4C 17 06       | 00D4..00DA  [EBP-4CH] a  pointer&lt;br /&gt;38 0E 03       | 00E2..00E5  [EBP-38H] a  pointer&lt;br /&gt;3C 4A 11       | 012C..013D  [EBP-3CH] a  pointer&lt;br /&gt;40 0B 06       | 0137..013D  [EBP-40H] a  pointer&lt;br /&gt;44 0E 03       | 0145..0148  [EBP-44H] a  pointer&lt;br /&gt;B8 5A 40       | 005A        reg EAX becoming live&lt;br /&gt;F1 07          | 0071        reg EAX becoming dead&lt;br /&gt;40             | 0071        reg EAX becoming live&lt;br /&gt;F2 01          | 008A        reg EAX becoming dead&lt;br /&gt;F0 43          | 0095        reg EAX becoming live&lt;br /&gt;F0 03          | 00A0        reg EAX becoming dead&lt;br /&gt;40             | 00A0        reg EAX becoming live&lt;br /&gt;03             | 00A3        reg EAX becoming dead&lt;br /&gt;BF 40          | 00A3        reg EAX becoming live (iptr)&lt;br /&gt;03             | 00A6        reg EAX becoming dead&lt;br /&gt;F0 43          | 00B1        reg EAX becoming live&lt;br /&gt;F1 BF 52       | 00C3        reg EDX becoming live (iptr)&lt;br /&gt;16             | 00C9        reg EDX becoming dead&lt;br /&gt;F0 4E          | 00D7        reg ECX becoming live&lt;br /&gt;53             | 00DA        reg EDX becoming live&lt;br /&gt;0D             | 00DF        reg ECX becoming dead&lt;br /&gt;10             | 00DF        reg EDX becoming dead&lt;br /&gt;4E             | 00E5        reg ECX becoming live&lt;br /&gt;05             | 00EA        reg EAX becoming dead&lt;br /&gt;08             | 00EA        reg ECX becoming dead&lt;br /&gt;BF 44          | 00EE        reg EAX becoming live (iptr)&lt;br /&gt;06             | 00F4        reg EAX becoming dead&lt;br /&gt;F5 45          | 0129        reg EAX becoming live&lt;br /&gt;BF 4E          | 012F        reg ECX becoming live (iptr)&lt;br /&gt;0D             | 0134        reg ECX becoming dead&lt;br /&gt;56             | 013A        reg EDX becoming live&lt;br /&gt;4B             | 013D        reg ECX becoming live&lt;br /&gt;0D             | 0142        reg ECX becoming dead&lt;br /&gt;10             | 0142        reg EDX becoming dead&lt;br /&gt;4E             | 0148        reg ECX becoming live&lt;br /&gt;05             | 014D        reg EAX becoming dead&lt;br /&gt;08             | 014D        reg ECX becoming dead&lt;br /&gt;FF             | &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you look for usages of EBP-0CH in the code, you'll find first the initialization to 0:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00d3010e 33c0            xor     eax,eax&lt;br /&gt;00d30110 8945f4          mov     dword ptr [ebp-0Ch],eax&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;then it's population with the address of the first element in &lt;b&gt;byteArray&lt;/b&gt; (itself stored as an object reference at location EBP-2CH).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00d3019a 8b45d4          mov     eax,dword ptr [ebp-2Ch]&lt;br /&gt;00d3019d 83780400        cmp     dword ptr [eax+4],0&lt;br /&gt;00d301a1 7705            ja      00d301a8&lt;br /&gt;00d301a3 e854c13979      call    mscorwks!JIT_RngChkFail (7a0cc2fc)&lt;br /&gt;00d301a8 8d4008          lea     eax,[eax+8] (here is the fixed(byte *p = byteArray) statement)&lt;br /&gt;00d301ab 8945f4          mov     dword ptr [ebp-0Ch],eax&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The last reference is interesting, and seems to disprove my assertion that the pointer is only protected to the last reference. At around the place where the closing curly brace for the fixed statement is, we have:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00d30257 33d2            xor     edx,edx&lt;br /&gt;00d30259 8955f4          mov     dword ptr [ebp-0Ch],edx&lt;br /&gt;00d3025c 90              nop&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Wow. I am surprised and shocked! It looks like indeed the pointer is held live until the end of the scope. This raises more questions...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-7067966867409290214?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/11/fixed-statement-not-what-you-expect-or.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-8566252093069125612</guid><pubDate>Thu, 12 Nov 2009 07:43:00 +0000</pubDate><atom:updated>2009-11-11T23:46:36.685-08:00</atom:updated><title>Managed C++ IS good :-)</title><description>After my ill-advised rant about managed C++ I learned something interesting. Managed C++ is a great bridge between a C# model and unmanaged C++ code, especially if your method signatures are kind of complex. Managed C++ does a better (quicker) job of marshaling between it's module and the unmanaged C++ module than PINVOKE does.&lt;br /&gt;&lt;br /&gt;Also, you don't have to learn those fancy PInvoke attributes and duplicate structures in C# and C++.&lt;br /&gt;&lt;br /&gt;Therefore, managed C++ is the most elegant solution to bridge between C# and unmanaged C++.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-8566252093069125612?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/11/managed-c-is-good.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-1214628033888028042</guid><pubDate>Thu, 24 Sep 2009 13:08:00 +0000</pubDate><atom:updated>2009-09-24T06:23:19.715-07:00</atom:updated><title>IDisposable tutorial</title><description>Recently at work we had to review our understanding of IDisposable. I wrote this little article to help me and everyone else get it nailed. For me, it took visualizing what happens at the time of an explicit call to Dispose() and what happens when a destructor is run. The difference between those two scenarios motivates and explains the code.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Why is it so complicated?&lt;/h2&gt;&lt;br /&gt;Beyond knowing that we might have something to cleanup, it's hard to understand why the mechanics of doing it appear so complex. The best way to understand it is to visualize the two very different contexts your cleanup code can be called in.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The first case, somebody called Dispose() on your object:&lt;/b&gt; This is easy to understand. Somebody has your object pointer, they make that explicit call, and then (hopefully) they set the pointer to null or let it fall out of scope. Only a nimrod would keep making calls on your object, right? In this case you get to do your cleanup. You can do anything you want, in fact! Do you want to send mail to somebody? No problem! Your object is alive, all of it's children objects are alive...go crazy!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The second case, the Finalizer Thread called your destructor:&lt;/b&gt; Here is where things go off the rails. You can't do anything you want. If you try to make calls on some of your member objects, you may find to your dismay that they've already been finalized, and won't respond the way you hoped. In effect, they are dead or dying. You are wandering around in a chaotic battlefield! The only thing you can do safely is release &lt;b&gt;unmanaged resources.&lt;/b&gt; These are file handles or pointers to memory that the Garbage Collector knows nothing about. And you have to hurry. If you block the Finalizer Thread, you end up blocking the whole runtime. So in this case, you definitely have to restrict yourself. Here are the rules:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Don't make blocking calls&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Don't examine/change/even-think-about member variables that are objects&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Why&lt;/b&gt; can't I touch those object member variables, you ask? The reason is that the finalizer thread operates on a list of objects ready for finalization. The objects are in that list in no particular order. The fact that &lt;b&gt;your object&lt;/b&gt; refers to the child object carries no weight anymore. Once your object was marked for finalization, your objects &lt;b&gt;opinion&lt;/b&gt; about what objects are important no longer matters. That is why it's dangerous to try to use any object member fields.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;But I don't have a destructor, you say?&lt;/b&gt; Okay. In that case, when your object goes out of scope nothing will happen. Of course, if you actually have the responsibility to clean something up this is not so good...&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Enter Dispose(bool disposing)&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Microsoft has established a convention to make these two different cases easy to distinguish in code. In a nutshell:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class A : IDisposable {&lt;br /&gt;    ~A() {&lt;br /&gt;        Dispose(false);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void Dispose(bool disposing) {&lt;br /&gt;        if(disposing) {&lt;br /&gt;            // Somebody actually called Dispose()!&lt;br /&gt;            // Let me send mail and open a web browser here&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Put code here that needs to run even if we are just called by the finalizer&lt;br /&gt;        // Remember, it should only clean up unmanaged resources. No referring to member objects!&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void Dispose() {&lt;br /&gt;        Dispose(true);&lt;br /&gt;        GC.SuppressFinalize(this);      &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The "disposing" parameter is confusing. Sometimes, people write it as "finalizing" and reverse the true and false constants in the code above. Stick with disposing though, it seems to be winning the war of convention. Just remember: &lt;b&gt;if disposing is true, then I came in here from an explicit call to Dispose(), and not from a finalizer.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I recommend to always create a &lt;b&gt;protected virtual void Dispose(bool disposing)&lt;/b&gt; method in your class that implements dispose. Then, make your implementation of &lt;b&gt;Dispose()&lt;/b&gt; look exactly like the code above. Make your destructor only do one thing...call &lt;b&gt;Dispose(false)&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;More enhancements&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;This is purely syntactic sugar, but lots of folks like to do this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class A : IDisposable {&lt;br /&gt;    ~A() {&lt;br /&gt;        Dispose(false);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void DisposeManagedResources() {&lt;br /&gt;        // Send mail and open a web browser here!&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void DisposeUnmanagedResources() {&lt;br /&gt;        // Close file handles here. Be careful what you do!&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void Dispose(bool disposing) {&lt;br /&gt;        if(disposing) {&lt;br /&gt;            // Somebody actually called Dispose()!&lt;br /&gt;            DisposeManagedResources();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        DisposeUnmanagedResources();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void Dispose() {&lt;br /&gt;        Dispose(true);&lt;br /&gt;        GC.SuppressFinalize(this);      &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you follow this pattern you can forget about the Dispose() method alltogether. You can forget about remembering what to do if &lt;b&gt;disposing&lt;/b&gt; is true or false. You just put your two kinds of cleanup code in the provided methods. We do this pretty often in our codebase.&lt;br /&gt;&lt;br /&gt;Another enhancement is a &lt;b&gt;disposed&lt;/b&gt; boolean variable. This ensures that cleanup is only done once. I think that if you set your fields to null, and do a null test on the way in then you don't need this, but perhaps I'm saving a penny to lose a pound. :-). Here is the code above modified to use a disposing variable. NOTE: this doesn't make the code any more thread safe. It just frees you from having to be careful in your cleanup code when it comes to null checks. &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class A : IDisposable {&lt;br /&gt;&lt;br /&gt;    private bool disposed;&lt;br /&gt;&lt;br /&gt;    ~A() {&lt;br /&gt;        Dispose(false);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void DisposeManagedResources() {&lt;br /&gt;        // Send mail and open a web browser here!&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void DisposeUnmanagedResources() {&lt;br /&gt;        // Close file handles here. Be careful what you do!&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected virtual void Dispose(bool disposing) {&lt;br /&gt;        if(!disposed) {&lt;br /&gt;            if(disposing) {&lt;br /&gt;                // Somebody actually called Dispose()!&lt;br /&gt;                DisposeManagedResources();&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            DisposeUnmanagedResources();&lt;br /&gt;            disposed = true;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void Dispose() {&lt;br /&gt;        Dispose(true);&lt;br /&gt;        GC.SuppressFinalize(this);      &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Hey, this is getting hard!&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Stay with me man, breath! We are almost there. Now, for a simple class the code we have above is perfect, and absolutely correct. If you are doing a code review, and you can't map the dispose logic of the class one-for-one to the logic above, then there is a bug in that code.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;But...&lt;/b&gt; what about class hierarchies? This is actually a big problem. Because if your understanding of &lt;b&gt;IDisposable&lt;/b&gt; for the one class case is a bit fuzzy, it will really fall apart when you consider a class hierarchy. But if you really understand the pattern above, and the reasons behind it, then you'll make correct and logical decisions when faced with creating, altering or debugging the dispose logic in a class hierarchy.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The implementer of IDisposable has responsibilities&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;In a class hierarchy, the first class (call it B) who chooses to implement the IDisposable interface has a very concrete responsibility:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Implement &lt;b&gt;public sealed void Dispose()&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Be nice and implement &lt;b&gt;protected virtual void Dispose(bool disposing)&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implement a destructor that calls Dispose(false)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Now, if you have class C, which derives from B, then you only have to do one thing in C to carry on the tradition of correct dispose behavior:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    class C : B {&lt;br /&gt;&lt;br /&gt;        protected override void Dispose(bool disposing) {&lt;br /&gt;            if(disposing) {&lt;br /&gt;                // Dispose of C managed resources&lt;br /&gt;            }&lt;br /&gt;            // Dispose of C unmanaged resources here&lt;br /&gt;    &lt;br /&gt;            base.Dispose(disposing); // Give B a chance to do it's work.&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What if C doesn't have any special work to do for dispose? Neither managed nor unmanaged resources to clean up? In that case C doesn't have to implement &lt;b&gt;Dispose(bool disposing)&lt;/b&gt;. Yay.&lt;br /&gt;&lt;br /&gt;Note the call to the base class Dispose(disposing) method. That is very important. Note that this call is at the &lt;b&gt;end&lt;/b&gt; of the Dispose(disposing) method. This reflects that C's resources are created after B's resources, and therefore C's resources should be cleaned up before B's resources are.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;I don't have to implement IDisposable do I?&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;One case where you should implement IDisposable but is not very obvious is when your &lt;b&gt;member variables implement IDisposable.&lt;/b&gt; The problem is what if your member variable is a FileStream. Now, it's true, when your object disappears, eventually the finalizer will run and find the FileStream object, call it's destructor, which will call Dispose(false) and the unmanaged resources will ultimately be cleaned up. But it's kind of rude.&lt;br /&gt;&lt;br /&gt;You see, the FileStream advertised that he is ready and willing to clean up the moment you snap your fingers and call Dispose() on him! But if you don't implement IDisposable yourself so that a user of your class (who can't see the FileStream) can take advantage of that behavior, well then...a baby cries somewhere. Very loudly.&lt;br /&gt;&lt;br /&gt;Of course, if you make sure to clean up that member variable before your object falls out of scope (maybe you have a "Close()" method or some convention like that), then you can sleep well again. However, it's pretty easy to implement IDisposable, now that you know what's going on!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-1214628033888028042?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/09/idisposable-tutorial.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-8977611584475564558</guid><pubDate>Thu, 10 Sep 2009 15:29:00 +0000</pubDate><atom:updated>2009-09-10T08:33:12.393-07:00</atom:updated><title>Managed C++</title><description>I don't understand why to use this. First bad: arcane new syntax for managed work (okay, not new, but I've been out of the .NET world for quite a while). But secondly, you don't get the kind of performance profile you'd expect for C/C++.&lt;br /&gt;&lt;br /&gt;At our company we recently did a test and discovered that native C++ is 20 times faster than managed C++. This led me to coin a phrase of which I remain inordinately proud:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Managed C++ has all the simplicity and clarity of the C++ language and the stunning performance profile of C#.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Needless to say, we are converting those managed C++ libraries to native C++...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-8977611584475564558?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/09/managed-c.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-8442014119902217552</guid><pubDate>Wed, 12 Aug 2009 11:11:00 +0000</pubDate><atom:updated>2009-08-12T04:14:13.295-07:00</atom:updated><title>vshost and /3GB problem</title><description>Yesterday I found that if you debug a process in Visual Studio 2008 on a machine with /3GB enabled, then the Visual Studio Hosting Process (on by default in the debug properties pane) will annoyingly reserve a 1gig chunk of memory for itself. This cancels out any benefit you hope to acquire by running with a 3gig address space!&lt;br /&gt;&lt;br /&gt;I don’t know why. But in the meantime, I’ve turned off this hosting option in the Prost8 vcproject file.&lt;br /&gt;&lt;br /&gt;Just because it’s fun to see:&lt;br /&gt;&lt;br /&gt;From output !sos.vmmap:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;...&lt;br /&gt;7fffe000-7fffefff 00001000  RdWr          RdWr          Commit   Private&lt;br /&gt;7ffff000-7fffffff 00001000  RdWr          RdWr          Commit   Private&lt;br /&gt;80000000-bffdffff 3ffe0000  Rd                          Reserve  Private (that is a lot of reserved mem!)&lt;br /&gt;bffe0000-bffeffff 00010000  Rd            NA            Reserve  Private&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;With hosting turned off:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;...&lt;br /&gt;7ffe1000-7ffeffff 0000f000                NA            Free&lt;br /&gt;7fff0000-7fffffff 00010000  NA                          Reserve  Private&lt;br /&gt;80000000-8000ffff 00010000  NA                          Reserve  Private&lt;br /&gt;80010000-bff47fff 3ff38000                NA            Free  (I like this much better, it gets used by us over time)&lt;br /&gt;bff48000-bff48fff 00001000  RdWr          RdWr          Commit   Private&lt;br /&gt;bff49000-bff49fff 00001000  RdWr          RdWr          Commit   Private&lt;br /&gt;bff4a000-bff4afff 00001000  RdWr          RdWr          Commit   Private&lt;br /&gt;bff4b000-bff4bfff 00001000  RdWr          RdWr          Commit   Private&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-8442014119902217552?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/08/vshost-and-3gb-problem.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3138926820109616470.post-7207111882714273086</guid><pubDate>Wed, 12 Aug 2009 10:15:00 +0000</pubDate><atom:updated>2009-08-12T03:16:08.089-07:00</atom:updated><title>Welcome!</title><description>Here is my blog for technical notes. Maybe something I find interesting about Visual Studio, or MATLAB, or iTunes, or just about anything.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3138926820109616470-7207111882714273086?l=www.mountainwerks.org%2Fdeathstarplayset'/&gt;&lt;/div&gt;</description><link>http://www.mountainwerks.org/deathstarplayset/2009/08/welcome.html</link><author>noreply@blogger.com (Michael Stanton)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item></channel></rss>
