1

I want to examine the contraction / expansion of stack based on local variable declarations and a function call. To do so, first I used the following C-style C++ code -

#include <stdio.h>

void MyFunc()
{
    int k = 3;
    printf("%d: %p\n", k, &k);
}

int main()
{
    int i = 1;
    printf("%d: %p\n", i, &i);

    int j = 2;
    printf("%d: %p\n", j, &j);

    MyFunc();

    int l = 4;
    printf("%d: %p\n", l, &l);

    return 0;
}

Compiling using clang - clang -o outputs/Example2.out Example2.cpp produced the following output -

1: 0x7ffd216a8818
2: 0x7ffd216a8814
3: 0x7ffd216a87ec
4: 0x7ffd216a8810

Based on the explanation (here)[Does stack grow upward or downward?, the output makes sense. As we allocate the new local variable j, the stack address reduces by 0x4. Similarly, when the function is called, there is a bigger reduction in address between outputs 2 and 3. And finally, when the function returns there is an expansion in the address (between 3 and 4).

But, if I use the iostream library for outputting the variables and their addresses (and compile using g++, I seem to get some discrepancies) -

#include <iostream>

void MyFunc()
{
    int k = 3;
    std::cout << k << ": " << &k << "\n";
}

int main()
{
    int i = 1;
    std::cout << i << ": " << &i << "\n";

    int j = 2;
    std::cout << j << ": " << &j << "\n";

    MyFunc();

    int l = 4;
    std::cout << l << ": " << &l << "\n";

    return 0;
}

Compiling using - g++ -Wall -Werror -o outputs/Example.out Example.cpp, yields the following output -

1: 0x7ffda2bb7fdc
2: 0x7ffda2bb7fe0
3: 0x7ffda2bb7fb4
4: 0x7ffda2bb7fe4

In this case, we see that the stack expanded by 0x4 from 1 to 2 (i.e. when j was declared). However, during the function call, the address contracted (from output 2 to 3 by 0x2c). Based on the answer (here)[Does stack grow upward or downward?, I understand that the stack grows either upwards or downwards based on the architecture.
In the first case, the stack contracted during local variable allocation / function call. But here, the stack expands during local variable declaration but contracts during function call.

Is there an explanation to this?

Ratus
  • 107
  • 1
  • 6
  • You will be more surprised if you build your program with enabled optimization. – 273K Oct 05 '19 at 07:06
  • All, what you observe, is implementation defined. Don't bother with this, if you're not a developer of compilers. Don't forget about exception handling. Some stuff for it is placed on the stack. – 273K Oct 05 '19 at 07:09
  • Even in your 2nd sample, you can see that your stack grows downwards. `3: 0x7ffda2bb7fb4` is still the lowest address of all. I would expect that storage for local variables in `main()` is allocated at once (in both cases). Which local variable uses which address is assigned by the compiler somehow. It seems that the order varies between samples and compilers. But, @S.M. already gave the reason... If in doubt, try your examples on [Compiler Explorer](https://gcc.godbolt.org/z/RQBOTD). The storage for `i`, `j`, and `l` in `main()` is provided in this one line: `31 sub rsp, 16`. ;-) – Scheff's Cat Oct 05 '19 at 07:57

0 Answers0