<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Be aware:  a new section in my blog</title><link>http://blogs.msdn.com/slavao/archive/2005/02/22/377837.aspx</link><description>Periodically, I bump into unusual behavior, features, of compiler, operating system, strange design and coding decisions made by someone else that makes me wonder. After giving it some thought, I often come to the conclusion that behavior or observed</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: Be aware:  a new section in my blog</title><link>http://blogs.msdn.com/slavao/archive/2005/02/22/377837.aspx#379952</link><pubDate>Fri, 25 Feb 2005 01:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:379952</guid><dc:creator>Lemo</dc:creator><description>Hi Slava,&lt;br&gt;First of all, great blog, please keep posting!&lt;br&gt;&lt;br&gt;Now on the matter at hand – I don’t want to get into the ‘declare locals on top vs. declare them when you need them’, but the point you brought up is not valid – what locals you’ll see in windbg depends on what locals are left on the stack after the optimizations, not on the location they are declared.&lt;br&gt;&lt;br&gt;Here is an example: (limiting the discussion to windbg and ms c++ compiler)&lt;br&gt;&lt;br&gt;&lt;br&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br&gt;&lt;br&gt;int main()&lt;br&gt;{&lt;br&gt;    int i = rand();&lt;br&gt;    int j = rand();&lt;br&gt;&lt;br&gt;    {&lt;br&gt;        int k = rand();&lt;br&gt;        int l = rand();&lt;br&gt;&lt;br&gt;        {&lt;br&gt;            int m = rand();&lt;br&gt;            int n = rand();&lt;br&gt;&lt;br&gt;            {&lt;br&gt;                int o = rand();&lt;br&gt;                int p = rand();&lt;br&gt;&lt;br&gt;                {&lt;br&gt;                    int q = i + j + k + l + m + n + o + p;&lt;br&gt;                    return q;&lt;br&gt;                }&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;br&gt;Now if you compile this with /Od windbg will follow the scope and display the locals as you would expect. If you compile the same thing with /O2 things are different.&lt;br&gt;Here is what I’m seeing with my version of the compiler:&lt;br&gt;&lt;br&gt;0:000&amp;gt; dv -V&lt;br&gt;0012fee0 @ebp-0x04               m = 1245120&lt;br&gt;0012fedc @ebp-0x08               n = 29694656&lt;br&gt;0012fed8 @ebp-0x0c               o = 2147348480&lt;br&gt;&lt;br&gt;PS: even funnier in this case is that the generated code actually uses ebp for one of the locals (‘l’ I think), so even if m, n, o are on the stack the debugger is unable to show them:&lt;br&gt;&lt;br&gt;0:000&amp;gt; dv -V&lt;br&gt;00006780 @ebp-0x04               m = &amp;lt;Memory access error&amp;gt;&lt;br&gt;0000677c @ebp-0x08               n = &amp;lt;Memory access error&amp;gt;&lt;br&gt;00006778 @ebp-0x0c               o = &amp;lt;Memory access error&amp;gt;&lt;br&gt;</description></item><item><title>re: Be aware:  a new section in my blog</title><link>http://blogs.msdn.com/slavao/archive/2005/02/22/377837.aspx#379973</link><pubDate>Fri, 25 Feb 2005 02:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:379973</guid><dc:creator>Slava Oks</dc:creator><description>Lemo, you are exactly correct. Yes, it definitely depends on the optimizations compiler decides to make. For example if local variable gets used in the first part of the function and never gets touched latter, compiler can use register and never allocate memory for it on the stack. Another example of common optimizations, that I have seen multiple times, the compiler would use the same stack location for different variables.&lt;br&gt;From my personal experience, especially with function containing lots of locals compiler would usually optimize out locals in the inner scope rather than in outter. I guess this happens due to isolated use of inner variables where compiler could make better decisions.  However I am not a compiler guru this is only speculations at this point. &lt;br&gt;&lt;br&gt;Your example is interesting, compiler actually decided to use registers ebx and edi for i and j. I think it is mostly due to simplicity of the function.&lt;br&gt;&lt;br&gt;0:000&amp;gt; uf main&lt;br&gt;test!main [e:\yukon\mainline\sql\ntdbms\dbgtools\test\repro2.cpp @ 5]:&lt;br&gt;    5 01001180 55               push    ebp&lt;br&gt;    5 01001181 8bec             mov     ebp,esp&lt;br&gt;    5 01001183 83ec14           sub     esp,0x14&lt;br&gt;    5 01001186 53               push    ebx&lt;br&gt;    5 01001187 56               push    esi&lt;br&gt;    6 01001188 8b3500100001     mov     esi,[test!_imp__rand (01001000)]&lt;br&gt;    6 0100118e 57               push    edi&lt;br&gt;    6 0100118f ffd6             call    esi&lt;br&gt;    6 01001191 8bf8             mov     edi,eax &amp;lt;==== this is i&lt;br&gt;    7 01001193 ffd6             call    esi&lt;br&gt;    7 01001195 8bd8             mov     ebx,eax &amp;lt;==== this is j&lt;br&gt;   10 01001197 ffd6             call    esi&lt;br&gt;   10 01001199 8945ec           mov     [ebp-0x14],eax&lt;br&gt;   11 0100119c ffd6             call    esi&lt;br&gt;   11 0100119e 8945f0           mov     [ebp-0x10],eax&lt;br&gt;   14 010011a1 ffd6             call    esi&lt;br&gt;   14 010011a3 8945f4           mov     [ebp-0xc],eax&lt;br&gt;   15 010011a6 ffd6             call    esi&lt;br&gt;   15 010011a8 8945f8           mov     [ebp-0x8],eax&lt;br&gt;&lt;br&gt;&lt;br&gt;   18 010011ab ffd6             call    esi&lt;br&gt;   18 010011ad 8945fc           mov     [ebp-0x4],eax&lt;br&gt;   19 010011b0 ffd6             call    esi&lt;br&gt;   19 010011b2 0345fc           add     eax,[ebp-0x4]&lt;br&gt;   23 010011b5 0345f8           add     eax,[ebp-0x8]&lt;br&gt;   23 010011b8 0345f4           add     eax,[ebp-0xc]&lt;br&gt;   23 010011bb 0345f0           add     eax,[ebp-0x10]&lt;br&gt;   23 010011be 0345ec           add     eax,[ebp-0x14]&lt;br&gt;   23 010011c1 03c3             add     eax,ebx&lt;br&gt;   23 010011c3 03c7             add     eax,edi&lt;br&gt;   23 010011c5 5f               pop     edi&lt;br&gt;   23 010011c6 5e               pop     esi&lt;br&gt;   23 010011c7 5b               pop     ebx&lt;br&gt;   30 010011c8 8be5             mov     esp,ebp&lt;br&gt;   30 010011ca 5d               pop     ebp&lt;br&gt;   30 010011cb c3               ret&lt;br&gt;&lt;br&gt;In my case, I used /Ox, I could actually see the variables in the debugger&lt;br&gt;&lt;br&gt;0:000&amp;gt; dv&lt;br&gt;              l = 26500&lt;br&gt;              k = 6334&lt;br&gt;              m = 19169&lt;br&gt;              n = 15724&lt;br&gt;              o = 11478&lt;br&gt;0:000&amp;gt; dv -V&lt;br&gt;000aff74 @ebp-0x10               l = 26500&lt;br&gt;000aff70 @ebp-0x14               k = 6334&lt;br&gt;000aff78 @ebp-0x0c               m = 19169&lt;br&gt;000aff7c @ebp-0x08               n = 15724&lt;br&gt;000aff80 @ebp-0x04               o = 11478&lt;br&gt;</description></item></channel></rss>