Memory free of garbage until variable assignment

I have a simple C program:

#include <stdio.h>

int main()
{
    int i;
    for(i = 0; i < 10; i++)
        printf("Hello\n");

    return 0;
}

      

I will compile it using gcc:

gcc -g test.c

      

Then I started the debugger:

gdb -q ./a.out

      

I set a breakpoint in main and ran:

(gdb) break main
(gdb) run

      

Then I let it run until it hits a breakpoint and tries to display the build instruction in the address rip, currently specifying:

(gdb) x/i $rip
=> 0x400538 <main+8>:   mov    DWORD PTR [rbp-0x4],0x0

      

It looks like the following statement initializes my local variable i with the value 0. Since it hasn't executed the statement yet, I expect there to be a garbage value here.

(gdb) x/4xb $rbp-4
0x7fffffffe0ec: 0x00    0x00    0x00    0x00

      

It doesn't look like garbage values, it looks like everything was already null. The breakpoint must stop the program before any of the main code is executed.

What am I missing here? Shouldn't this memory location contain random garbage values ​​before initializing local variable i?

+3


source to share


4 answers


It doesn't look like garbage values, it looks like everything was already null.

I modified your example to show that this is just a coincidence.

#include <stdio.h>

int main()
{
  int i1;
  int i2;
  int i3;
  int i4;
  int i5;
  int i6;
  int i;

  for(i = 0; i < 10; i++)
    printf("Hello\n");

  return 0;
}

      

(gdb) start
Temporary breakpoint 1 at 0x4005ac: file main.cpp, line 13.
Starting program: /home/a.out

Temporary breakpoint 1, main () at main.cpp:13
13        for(i = 0; i < 10; i++)
(gdb) info locals
i1 = 0
i3 = 0
i5 = 32767
i = 0
i2 = 4195520
i4 = -7856
i6 = 0

      



You see, different meanings are possible.

As for your example, the value at this address changes at least twice before reaching main()

. Just set watch

the address for that and you will see that it is changed in the functions called before main ():

(gdb) watch *(int*)0x7fffffffe06c
Hardware watchpoint 1: *(int*)0x7fffffffe06c

(gdb) r
Starting program: /home/a.out
Hardware watchpoint 1: *(int*)0x7fffffffe06c

Old value = 0
New value = 58
0x0000003a1d890880 in handle_intel () from /lib64/libc.so.6


Hardware watchpoint 1: *(int*)0x7fffffffe06c

Old value = 58
New value = 0
0x0000003a1d0146fd in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2

Hardware watchpoint 1: *(int*)0x7fffffffe06c

Old value = 0
New value = 1
0x00000000004005c3 in main () at main.cpp:7
7         for(i = 0; i < 10; i++)
#0  0x00000000004005c3 in main () at main.cpp:7

      

+3


source


The garbage value can be anything, including the value 0. The contents of this local variable are undefined until the time it is assigned a value. You cannot expect content to be of a certain type before this happens.

However, it is quite common for all local variables to be nullified during a debug build. If this is the case with gdb I have no idea. You can try printing out the contents of a variable before initializing it, and then building a release build without a debugger and see if the behavior has changed.



Most likely, however, the compiler chose to initialize the variable before the actual string i = 0. The compiler is free to reorder the program as long as it can determine that it will not affect the program's results. The compiler may have moved the null value to an earlier point in the program for performance reasons.

+2


source


You are misunderstanding what is meant by "garbage" (which is not even a formal term). Uninitialized objects in C have undefined meaning. This does not mean that the value is random, much less that it has any value as entropy (in fact, there was a huge OpenSSL / Debian fiasco over this misunderstanding long before Heartbleed happened and everyone realized that such a mess of OpenSSL). All this means that you cannot use the value . If you do this, you don't have a valid C program, but it is meaningless, and there is no point in trying to speculate about what it does (except, perhaps, if you are an attacker trying to exploit a vulnerability in the program).

+1


source


It doesn't look like garbage values

Zero in this context is a special case of "garbage value" (or more correctly undefined value) that you cannot rely on in any case, here is a slightly modified example that produces a different value for my compiler ( gcc 4.4.7

):

#include <stdio.h>

int main(void)
{
    int i, j, k;
    for(i = 0; i < 10; i++)
        printf("Hello\n");

    return 0;
}

      

and gdb

:

Breakpoint 1, main () at check.c:6
6       for(i = 0; i < 10; i++)
(gdb) x/i $pc
=> 0x4004cc <main+8>:   mov    DWORD PTR [rbp-0xc],0x0
(gdb) x/4xb $rbp-0xc
0x7fffffffe124: 0xff    0x7f    0x00    0x00

      

A good analogy for this might be a random number generator that returns zero. Zero is the same random value as 112

or 377

.

+1


source







All Articles