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
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
$ 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.
$ 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.
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
B to be identical, and print