Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it means "All memory allocated on the stack is known at compile time"?

Reading this great tutorial about Stack vs Heap, I've got a dubt about this phrase: All memory allocated on the stack is known at compile time.

I mean, if I'm within a for cycle that depends of user input (i from 0 to X), and within the for I allocate memory on the stack (such as create new instances of some classes and put inside a class-container), it can't know how will grow the stack when compile the program (it miss the input from user).

Am I misunderstand somethings?

like image 471
markzzz Avatar asked Feb 06 '23 12:02

markzzz


2 Answers

The statement made is a little bit simplified for the reader. You're right that the stack is dynamic in nature and the actual allocated amount can vary depending on dynamic input. Here is a simple example with a recursive function:

void f(int n)
{
    int x = n * 10;
    if(x == 0) return;

    std::cout << x << std::endl;
    f(n - 1);
}

int main()
{
    int n;
    std::cout << "Enter n: " << std::endl;
    std::cin >> n;
    f(n);
}

Here clearly the number of invocations of f, a recursive function, depends on the n entered by the user, so for any given instantiation the compiler cannot possibly know the exact memory address of the local variable x in f. However, what it does know is x's offset from the local stack frame, which is what I believe the example is referring to. A stack frame is a local area of the stack prepared every time a function invocation occurs. Within a given stack frame, locations of local variables are in fact known constant offsets relative to the beginning of the stack frame. This 'beginning' is saved in a standard register in every invocation, so all the compiler has to do to find the address of any local is to apply its fixed known offset to this dynamic 'base pointer'.

like image 133
Smeeheey Avatar answered Feb 24 '23 10:02

Smeeheey


I mean, if I'm within a for cycle that depends of user input (i from 0 to X), and within the for I allocate memory on the stack (such as create new instances of some classes and put inside a class-container), it can't know how will grow the stack when compile the program (it miss the input from user).

So you have a class container...

std::vector< SomeClass > vec;

...that's on the stack. Inside a loop you create a new instance of some class...

for ( size_t i = 0; i < X; ++i )
{
    SomeClass x;

...which is on the stack. When you put that into the container...

    vec.push_back( x );
}

...that container will store the instance on the heap.

You only ever have one SomeClass on the stack, and that fact is known at compile time. The stack doesn't grow beyond that one instance.

There are ways to grow the stack at runtime though (e.g. alloca()), so the generic statement made by the tutorial is not quite correct.

like image 26
DevSolar Avatar answered Feb 24 '23 11:02

DevSolar