A stack overflow occurs when a program uses more stack memory than is allocated by the system. Historically, the stack was used to store local variables, return addresses, and temporary data during function calls. In early implementations of C, the stack was quite small and not protected against overflow.
The issue arises when a function or a chain of function calls uses too many local variables or calls recursive functions without a termination condition, causing the program to write data beyond the allocated stack memory, leading to errors, crashes, and vulnerabilities.
The solution is to design memory-efficient functions, avoid deep or infinite recursions, and not place large objects on the stack. The operating system may prevent overflow through memory segment protection (guard pages), but the developer must write code that does not lead to overflow.
Example code that triggers a stack overflow due to infinite recursion:
void foo() { int arr[1000]; // A large local array only exacerbates the problem foo(); // Recursive call without exit } int main() { foo(); return 0; }
Key features:
What happens if you declare a very large local array inside a function (for example, int arr[1000000])?
Answer: A large local array can immediately consume the entire stack. Depending on the OS and compiler, this may result in a crash when the function is called or even crash the program.
Example code:
void func() { int arr[1000000]; // A lot of memory arr[0] = 1; }
Does recursion always lead to stack overflow?
Answer: No, recursion is useful if limited in depth. Overflow occurs only if the depth of recursion is high or not limited.
Can large static arrays be placed inside functions to save memory?
Answer: No, large static arrays within a function still occupy memory, but in the static data segment instead of the stack. This is not always economical, especially if temporary local memory is needed.
Example code:
void func() { static int arr[1000000]; // Not on the stack, but the static area is permanently occupied }
A programmer implemented quicksort through recursion to sort a large array, not limiting the depth of calls and not using exit conditions. The code led to stack overflow when processing real data.
Pros:
Cons:
Another programmer used an iterative implementation with a small custom stack on the heap, controlled the depth of recursion, and allocated large temporary arrays through malloc.
Pros:
Cons: