I recently learned about stacks, so I was experimenting to see what the stack size is and what happens when it overflows. I found out that on Unix the default stack size is 8 MiB, and that supports my findings since I cannot declare a string having size greater than or equal to 8 MiB in my main
function. However, when I declare a variable in main()
it affects other functions. For example:
#include <stdio.h>
void foo(void)
{
long int size = 1024*1024*2;
char str[size];
str[size - 1] = 'a';
printf("%c\n", str[size - 1]);
}
int main(int argc, char** argv)
{
long int size = 1024*1024*6;
char str[size];
str[size - 1] = 'a';
printf("%c\n", str[size - 1]);
foo();
return 0;
}
This code results in segmentation fault but if I make the string size 5 MiB in main()
then there is no segmentation fault. Does that mean my C program cannot allocate more than 8 MiB of RAM for local variables (of all functions)? If so, what IS the point of stacks?
No, each function doesn't get its own independent stack space. There's only one stack in your program and there's an limited finite amount of stack space available to you.
This LIFO behavior is exactly what a function does when returning to the function that called it.
All of the above process happens in the same stack memory. Each function does have its own space in the stack but every function gets its space allocated in the same stack. This is called the Global Call Stack of your program. It is used to store local variables which are used inside the function.
However, dynamically allocated space is stored on the heap. Heap is used to store dynamic variables. It is a region of process’ memory. malloc()
, calloc()
, resize()
all these inbuilt functions are generally used to store dynamic variables.
As for the stack overflow issue, the call stack size is limited. Only a certain amount of memory can be used. If many function calls happen, the stack space would eventually run out which would give you a stack overflow error which would most likely cause your program to crash.
If there are a lot of variables in your function or some variables which needs a huge amount of space in your program, then the stack space will eventually run out and it would cause a stack overflow. E.g. the following would probably give stack overflow in most cases and cause your program to crash:
int main() {
int A[100000][100000];
}
Hope this clears your doubt !
NOTE:
In an multi-threaded environment, each thread gets its own call stack space separately instead of having the same Global Call Stack. So, in an multi-threaded environment, the answer to your question will be YES.
Does that mean my c program cannot allocate more than 8MB of ram for local variables (of all functions) ?
Yes and no. Yes, your program can't use more space for local variables than the available stack space, whatever that is. But no, you're not limited to 8MB for all functions, you're only limited to that much total stack space for functions that are currently executing. A program might contain thousands of functions, but only a relative handful of those will be invoked at any given moment.
When your program calls a function, space is reserved on the stack for the function's return value and it's local variables. If that function calls another function, space will then be reserved for that next function's return value and local variables. When each function returns, the return value is read and the local variables and return value are popped off the stack. So functions only use stack space while they're executing.
If so, what's the point of stacks ?
The point is to provide the space needed for local variables, to facilitate returning a value to the caller, and to make allocating that space fast and efficient. Functions don't typically need huge amounts of storage for local variables, so 8MB is typically more than enough.
If you find that you need to allocate a large amount of memory, there are memory allocation functions that make that easy. Let's say you need to create a multi-megabyte string as in your example. You'd typically use a function like malloc()
or calloc()
to create that object on the heap instead of on the stack, and the only local variable you'd need is a pointer to the allocated memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With