1

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?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Abel Tadesse
  • 145
  • 5
  • `i` isn't an array. It's not initialized to any particular value. – Ross Ridge Dec 10 '16 at 19:37
  • 2
    It's undefined. – MrTux Dec 10 '16 at 19:40
  • 3
    Possible duplicate of [Non-static variable initialization](http://stackoverflow.com/questions/8743445/non-static-variable-initialization) – MrTux Dec 10 '16 at 19:41
  • 1
    This asm never writes to the stack slot that it is evidently using as source of the read from `i`, which is an oddly faithful translation, especially for GCC. – harold Dec 10 '16 at 19:55
  • 2
    Funnily enough, enabling optimization will explicitly return zero in all compilers on godbolt (gcc, clang, icc). PS: even though you claim your version is optimized, it apparently isn't. – Jester Dec 10 '16 at 20:25

2 Answers2

3

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.

Community
  • 1
  • 1
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
2

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.)

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 1
    @MadhavDatt It's completely undefined. The program could print `0`, `1,` `3446710249680232`, `giraffe` or `segmentation fault: core dumped`. – Ross Ridge Dec 10 '16 at 19:42
  • 1
    The value of `i` is indeterminate, and may be a trap representation. Attempting to use an indeterminate value leads to undefined behavior. – John Bode Dec 10 '16 at 20:40
  • 1
    @JohnBode: Note that x86 doesn't have trap representations for integers. That point applies to C in general, but not to how `i` is getting initialized in the OP's specific case. (See my answer which addresses that.) – Peter Cordes Dec 11 '16 at 01:46