1

I have the following code

int main(int argc, char *argv[]) {
    int value1 = 10;
    int value2 = 11;

    return 0;
}

When I debugged the code, &value2 was higher than &value1. That means that value2 was pushed to the stack first, then value1.

Is this a normal behavior of gcc?

Why does the gcc compile variables from bottom up?

Does clang also behave in the same way?

Thanks

Carol Ward
  • 699
  • 4
  • 17
  • On the architecture you are debugging the stack grows backwards. – KamilCuk Jan 27 '20 at 00:40
  • I'm using linux ubuntu, so this is specific to Ubuntu? When I looked at the assembly, the value1 is assigned a stack first but furthest away from the base pointer. This is normal for ubuntu I'm assuming? – Carol Ward Jan 27 '20 at 00:43
  • The direction in which the stack grows is irrelevant to how local variables are allocated. Almost certainly, space for `value1` and `value2` is allocated simultaneously, by adjusting the stack pointer by `2 * sizeof (int)` bytes -- plus space for compiler-defined bookkeeping (return address, etc.). The choice of how local variables are allocated relative to each other is arbitrary. – Keith Thompson Jan 27 '20 at 03:28

2 Answers2

3

The ordering of local variables on the stack is entirely implementation dependent and need not appear consistent.

When compiled the above code with gcc 4.8.5 and ran it, value1 had a higher address than value2 which is in contrast to what you saw.

I also tried running this in gdb:

int main(int argc, char *argv[]) {
    int value1 = 10;
    int x = 4;
    int value2 = 11;

    printf("&1=%p, &2=%p\n", &value1, &value2);
    return 0;
}

And got this:

(gdb) start
Temporary breakpoint 1 at 0x40053c: file x1.c, line 6.
Starting program: /home/dbush/./x1 

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe008) at x1.c:6
6       int value1 = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7.x86_64
(gdb) step
7       int x = 4;
(gdb) 
8       int value2 = 11;
(gdb) 
10      printf("&1=%p, &2=%p\n", &value1, &value2);
(gdb) p &value1
$1 = (int *) 0x7fffffffdf18
(gdb) p &value2
$2 = (int *) 0x7fffffffdf14
(gdb) p &x
$3 = (int *) 0x7fffffffdf1c
(gdb) 

In this case, the address of x comes after value1 and value2 even though it is defined between them.

What this shows is that you can't make any assumptions about the order of variables on the stack.

dbush
  • 205,898
  • 23
  • 218
  • 273
1

The C language standard does not impose any specific ordering in memory. This applies to variables in static storage (like global variables, functions and variables local to a compilation unit or local-static in a function), to variables on the heap (allocated with malloc et al.) local variables allocated on the stack.

In you particular case, the compiler might not allocate any memory at all (not even in processor registers) because the variables are never used. Hence when you are compiling with optimization turned on (-O2) for example, the variables will be optimized out and they will appear nowhere in the generated code.

How variables are located is figured out by the locator, in the case of GNU tools it's ld, this linker + locator. This in turn is directed by the linker description file. Thus, if you need a specific ordering or variables in static storage, you might do it by means of a custom linker description file.

In the case of local variables however, the location is unspecified (it is not even implementation defined because the compiler does not even specify where it puts such variables): Such variables might be put on the stack and later on be held in register(s) for some time; or they may be optimized out completely.

emacs drives me nuts
  • 2,785
  • 13
  • 23