Reputation: 145
I generated unoptimized code for the following c code:
#include<stdio.h>
int main(){
int i;
printf("%d\n", i);
}
and the generated code is:
.file "test.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",@progbits
Running the above assembly code gives 0 as an output.
My question is, how is the variable i
getting initialized to 0
?
Upvotes: 1
Views: 538
Reputation: 365911
NPE's answer tells you everything the C standard has to say about this program: the behaviour is (completely) undefined.
I'll take a stab at explaining why you happen to get zero from that un-optimized asm from gcc -O0
on Linux, now that the compiler has generated it.
As harold points out, it reads from stack memory that it didn't write. The Linux kernel gives your processes zeroed pages for its stack, to avoid information leaks. (Same with mmap(MAP_ANONYMOUS)
)
None of the startup code uses as much stack space as main
right before that call to printf
, so this load from it still finds that initial zeroed state.
Of course, after printf
returns, the stack below RSP will be dirty. Dynamic linking is done "lazily", so that happens right after the call printf
(which is actually call printf@plt
if you disassemble the linked object file with objdump -drwC -Mintel a.out
). That probably uses some stack space for temporary storage. (If you ever single-step into the first call to a library function in a dynamically linked binary, you'll see ~1 million instructions before execution reaches the actual library function code. [I forget how I measured that number, but I seem to recall doing something that told me it was maybe around 1M instructions.]) printf
itself will certainly push/pop some registers, and maybe use some other scratch space on the stack.
Upvotes: 3
Reputation: 500913
how is the variable i getting initialized to 0
It isn't. Your C code has undefined behaviour, and the assembly reflects that.
(Here and here is some old info on the startup state of a process on Linux. It is somewhat relevant, but doesn't invalidate the main point about undefined behaviour.)
Upvotes: 2