C++: How does the compiler know how much memory to allocate for each stack frame?

Viewed 1313

In the first answer here, the following was mentioned about the stack memory in C++:

When a function is called, a block is reserved on the top of the stack for local variables and some bookkeeping data.

This makes perfect sense on the top-level, and makes me curious about how smart compilers are when allocating this memory in and of itself, given the context of this question: Since braces themselves are not a stack frame in C (I assume this holds true for C++ as well), I want to check whether compilers optimize reserved memory based on variable scopes within a single function.

In the following I'm assuming that the stack looks like this before a function call:

--------
|main()|
-------- <- stack pointer: space above it is used for current scope
|      |
|      |
|      |
|      |
--------

And then the following after invoking a function f():

--------
|main()|
-------- <- old stack pointer (osp)
|  f() |
-------- <- stack pointer, variables will now be placed between here and osp upon reaching their declarations
|      |
|      |
|      |
|      |
--------

For example, given this function

void f() {
  int x = 0;
  int y = 5;
  int z = x + y;
}

Presumably, this will just allocate 3*sizeof(int) + some extra overhead for bookkeeping.

However, what about this function:

void g() {
  for (int i = 0; i < 100000; i++) {
    int x = 0;
  }
  {
    MyObject myObject[1000];
  }
  {
    MyObject myObject[1000];
  }
}

Ignoring compiler optimizations which may elide a lot of stuff in the above since really they do nothing, I'm curious about the following in the second example:

  • For the for loop: will the stack space be large enough to fit all 100000 ints?
  • On top of that, will the stack space contain 1000*sizeof(MyObject) or 2000*sizeof(MyObject)?

In general: does the compiler take variable scope into account when determining how much memory it will need for the new stack frame, before invoking a certain function? If this is compiler-specific, how do some well-known compilers do it?

2 Answers
Related