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 --version
gcc (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
.