user2793162
user2793162

Reputation:

How is stack memory organized?

I just want to make sure I get it right. Imagine the stack size for any program on my machine is 800 bytes (just example). Then, following code:

void f()
{
char x[300];
char y[300];
char z[300];
char t[300];
}

should overflow stack right (because 1200>800)?

Now my question is, is the below approach an Ok way to defeat above mentioned stack overflow problem?

void f()
{
   f1();
   f2();
}

where:

void f1()
{
    char x[300];
    char y[300];
}

void f2()
{
    char z[300];
    char t[300];
}

this way according to my reasoning each function consumes only 600 bytes (<800) of stack memory, so all should be OK. Am I right?

ps. I am not referring to "other" data that could take up space on stack for the sake of this example.

pps. In other words, is this the case, that each time, each function f(), f1(), and f2() get their "instance" of stack?

Upvotes: 12

Views: 955

Answers (4)

Klas Lindb&#228;ck
Klas Lindb&#228;ck

Reputation: 33273

pps. In other words, is this the case, that each time, each function f(), f1(), and f2() get their "instance" of stack?

When a function is called it will allocate memory for the duration of the call. When the function returns, the memory is returned.

In your example, f2() will use the same instance of the stack as f1(), but since f1() has returned when f2() is called, the stack memory used by f1() is free to be re-used by f2().

Stacks are allocated per thread, so in a multi-threaded program each thread will have its own stack.

Edit

It should be pointed out that the description above is how compilers usually implement local variables. The C standard does not specify that stacks need to be used, but it is the best solution (so far) for environments where an unknown amount of processes/threads need to share a limited amount of memory.

Edit 2

Dividing f into f1 and f2 is one way of reducing the stack memory consumption. Other ways are to allocate memory on the heap (with malloc/free) or statically (static allocation isn't thread-safe, so it reduces portability and reusability and should only be used as a last resort).

Say I had one local variable defined in f(), what would happen with it, when program entered inside f1()?

It would still be there. You can think of the stack as a pile of papers. Whenever you call a function, the caller adds a paper with the return address and space for the return value. The called function then adds another paper with the local variables. When a function returns, it removes the top paper (with its local variables) and jots down the return value on the next paper. The calling code reads the return value and removes the top paper, again exposing the paper with the caller's local variables.

Upvotes: 5

Zaheer Ahmed
Zaheer Ahmed

Reputation: 28528

Yes, when a compiler execute a program, it occupies or required the memory the current context required. So in first case when your function required more than available space it will throw exception.

While in second case firstly when it try to run main function (ideally) it required no memory.

main

so when it tries to run the f1(), which required memory allocation which is not greater than available memory so it will get executed successfully.

f1

on returning from function f1() memory will be de-allocated and your complete(ideally) will be available now f2() start getting run which again required the memory.

f2

So your program will successfully get executed.

Upvotes: 0

WhozCraig
WhozCraig

Reputation: 66194

While everyone else throws in their hats concerning "yes it helps", "no it won't", "makes no difference", etc. I'll tell you that what you're asking is so dependent on implementation it is not possible to get a straight universal answer. The variables you're describing are automatic, meaning their visibility and definition are limited by scope of their function. What goes on behind the curtain is entirely platform dependent.

I've already mentioned one case that an implementation could potentially have both functions automatic variables occupying memory, namely optimizing out the calls entirely and thus requiring enough occupation memory dedicated to automatic variables to have it all in one locality. You don't know and honestly you're better off not assuming you need to unless you're writing embedded, kernel or driver code where every byte counts and the platform is a foregone conclusion.

The C standard is very specific in not addressing things like this, leaving it to the implementations to fulfill. Search the C99 standard and you'll find the word "stack" exactly zero times. That isn't by accident.

That said, if you were designing a simple implementation yourself, consideration for what you're concerned with would be paramount in design, but unless you're going down that road (or the kernel/driver/embedded side-street where you already know the platform answer), there is simply no concrete way to say "it works this way..." Your implementation would likely simply do as you describe, the proverbial plate stack at the buffet diner. But that by no means can be used to conclude all (or even most) implementations would do the same. So long as they honor the rules put forth by the standard concerning automatic variables, the rest is literally the devil in the details.

Upvotes: 6

KARTHIK BHAT
KARTHIK BHAT

Reputation: 1420

Yes splitting up the function will save stack space since while function completes execution (last executable statement in that function is executed) and return's it clears the stack memory it used.

No data will be there (you stored in the char x[300] char y[300]) after the function f1() finishes it's execution

Upvotes: 1

Related Questions