Conflict between a Stanford tutorial and GCC Conflict between a Stanford tutorial and GCC c c

Conflict between a Stanford tutorial and GCC


Yes, yes, this is undefined behavior, because you're using the variable uninitialized1.

However, on the x86 architecture2, this experiment should work. The value isn't "erased" from the stack, and since it's not initialized in B(), that same value should still be there, provided the stack frames are identical.

I'd venture to guess that, since int a is not used inside of void B(), the compiler optimized that code out, and a 5 was never written to that location on the stack. Try adding a printf in B() as well - it just may work.

Also, compiler flags - namely optimization level - will likely affect this experiment as well. Try disabling optimizations by passing -O0 to gcc.

Edit: I just compiled your code with gcc -O0 (64-bit), and indeed, the program prints 5, as one familiar with the call stack would expect. In fact, it worked even without -O0. A 32-bit build may behave differently.

Disclaimer: Don't ever, ever use something like this in "real" code!

1 - There's a debate going on below about whether or not this is officially "UB", or just unpredictable.

2 - Also x64, and probably every other architecture that uses a call stack (at least ones with an MMU)


Let's take a look at a reason why it didn't work. This is best seen in 32 bit, so I will compile with -m32.

$ gcc --versiongcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)

I compiled with $ gcc -m32 -O0 test.c (Optimizations disabled). When I run this, it prints garbage.

Looking at $ objdump -Mintel -d ./a.out:

080483ec <A>: 80483ec:   55                      push   ebp 80483ed:   89 e5                   mov    ebp,esp 80483ef:   83 ec 28                sub    esp,0x28 80483f2:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc] 80483f5:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax 80483f9:   c7 04 24 c4 84 04 08    mov    DWORD PTR [esp],0x80484c4 8048400:   e8 cb fe ff ff          call   80482d0 <printf@plt> 8048405:   c9                      leave   8048406:   c3                      ret    08048407 <B>: 8048407:   55                      push   ebp 8048408:   89 e5                   mov    ebp,esp 804840a:   83 ec 10                sub    esp,0x10 804840d:   c7 45 fc 05 00 00 00    mov    DWORD PTR [ebp-0x4],0x5 8048414:   c9                      leave   8048415:   c3                      ret    

We see that in B, the compiler reserved 0x10 bytes of stack space, and initialized our int a variable at [ebp-0x4] to 5.

In A however, the compiler placed int a at [ebp-0xc]. So in this case our local variables did not end up at the same place! By adding a printf() call in A as well will cause the stack frames for A and B to be identical, and print 55.


It's undefined behavior. An uninitialized local variable has an indeterminate value, and using it will lead to undefined behavior.


One important thing to remember - don't ever rely on something like that and never use this in real code! It's just an interesting thing(which even isn't always true), not a feature or something like that. Imagine yourself trying to find bug produced by that kind of "feature" - nightmare.

Btw. - C and C++ are full of that kind of "features", here is GREAT slideshow about it:http://www.slideshare.net/olvemaudal/deep-c So if you want to see more similar "features", understand what's under the hood and how it's working just watch this slideshow - you won't regret and i'm sure that even most of experienced c/c++ programmers can learn a lot from this.