Stack Memory
Where does your data live when your program runs? Understanding stack memory vs heap memory is fundamental to writing efficient, bug-free code.
What Is Stack Memory?
Stack memory is a region of memory used for static memory allocation. It stores local variables, function parameters, and return addresses. It follows LIFO (Last In, First Out) behavior, which is why it is called a "stack."
When a function is called, the system allocates a block of memory on the stack for that function's local data. When the function returns, that block is automatically freed. No manual management is needed. This makes stack allocation extremely fast, typically just moving a pointer forward or backward by a few bytes.
Stack memory has a fixed size set by the operating system, usually between 1 MB and 8 MB. If you try to use more, you get a stack overflow error.
Learn how the call stack uses this memory
What Is Heap Memory?
Heap memory is a region used for dynamic memory allocation. When you create an object, array, or allocate memory at runtime (using new in C++, malloc in C, or object literals in JavaScript/Python), the memory comes from the heap.
The heap is much larger than the stack, limited only by available system RAM. However, heap allocation is slower because the system must find a free block of the right size and keep track of it. In garbage-collected languages, the heap is managed by the garbage collector, which periodically reclaims unused memory.
Stack analogies for understanding allocation patterns
Stack vs Heap Comparison
| Feature | Stack Memory | Heap Memory |
|---|---|---|
| Speed | Very fast (pointer arithmetic) | Slower (allocation algorithm) |
| Size | Small (1-8 MB typical) | Limited by available RAM |
| Allocation | Automatic (compiler/OS) | Manual or garbage-collected |
| Lifetime | Scope of the function | Until explicitly freed or GC'd |
| Fragmentation | None (contiguous) | Possible over time |
| Access | Direct (fast CPU cache) | Indirect (pointer/reference) |
| Thread safety | Each thread has its own stack | Shared, requires synchronization |
How Local Variables Use Stack Memory
When you declare a variable inside a function, it is stored on the stack. This includes integers, floats, booleans, characters, and pointers. The memory is allocated when the function is entered and freed when it returns.
void example() {
int x = 10; // stored on the stack
double y = 3.14; // stored on the stack
char c = 'A'; // stored on the stack
int *ptr = &x; // pointer on the stack, points to stack memory
}
In higher-level languages like JavaScript and Python, primitive values (numbers, strings, booleans) are stored on the stack (or in stack frames), while objects and arrays are allocated on the heap with a reference on the stack.
Stack implementation in JavaScript
How Dynamic Allocation Uses Heap Memory
When you need memory whose size is not known at compile time, or whose lifetime extends beyond the current function, you allocate it on the heap.
// C: malloc allocates on the heap
int *arr = malloc(100 * sizeof(int));
free(arr); // must free manually
// C++: new allocates on the heap
int *arr = new int[100];
delete[] arr;
// JavaScript: objects are allocated on the heap automatically
const obj = { name: "hello", values: [1, 2, 3] };
// garbage collector frees it when no longer referenced
// Python: everything is an object on the heap
data = [1, 2, 3] # heap allocated, reference counted
Stack Memory Limits and Overflow
Stack memory has a fixed, relatively small size. Common causes of stack overflow include:
- Infinite recursion: A function calling itself without a base case exhausts the stack.
- Very large local arrays: Declaring
int arr[1000000]inside a function tries to allocate millions of bytes on the stack. - Deep but finite recursion: Even valid recursion can overflow if the depth exceeds the stack limit.
Solutions include increasing the stack size (OS/compiler settings), converting recursion to iteration, or moving large data to the heap using dynamic allocation.
Memory Layout in a Running Program
When a program is loaded into memory, it is divided into several regions:
- Text segment: Contains the compiled machine code (read-only).
- Data segment: Contains global and static variables.
- Heap: Grows upward from the data segment. Used for dynamic allocation.
- Stack: Grows downward from the top of the address space. Used for function calls and local variables.
The heap and stack grow toward each other. If they meet, a stack overflow or out-of-memory condition occurs. The gap between them is the free space available for dynamic allocation.
Stack Memory in C
In C, all local variables are automatically allocated on the stack. This is called automatic storage duration. The compiler knows the exact size needed at compile time and adjusts the stack pointer accordingly.
void compute() {
int a = 5; // 4 bytes on stack
double b = 2.7; // 8 bytes on stack
char name[20]; // 20 bytes on stack
// all freed when function returns
}
C gives you direct control: you can use alloca() for stack allocation and malloc()/free() for heap allocation. This power comes with responsibility: forgetting to free heap memory causes leaks, and writing past stack buffers causes undefined behavior.
Stack Memory in Java, Python, and JavaScript
In managed languages, you do not directly control stack and heap allocation, but the same principles apply:
- Java: Local primitives and references live on the stack. Objects live on the heap. The JVM manages both. Stack size can be configured with
-Xss. - Python: Everything is an object on the heap, even integers. Function frames are on the call stack but reference heap objects. The reference limit is set by
sys.getrecursionlimit(). - JavaScript: The V8 engine stores primitive values in stack frames and objects/arrays on the heap. The garbage collector handles heap cleanup. The call stack limit is enforced by the engine.
Understanding this distinction helps you write code that avoids unnecessary heap allocations (for performance) and avoids deep recursion (to prevent stack overflow).
Key Takeaway
Stack memory is fast, automatic, and small. Heap memory is flexible, large, but slower. Know when your data lives on each one, and you will write faster, more reliable code. Avoid putting large data or deep recursion on the stack, and always free or let the garbage collector handle heap data.
Frequently Asked Questions
Why is stack memory faster than heap memory?
Stack memory is faster because it uses a simple pointer-based allocation scheme. When a function is called, the stack pointer simply moves forward to reserve space. No search is needed. Heap allocation requires finding a free block of the right size, which involves more complex algorithms and potential locking in multi-threaded programs.
What is the difference between stack overflow and heap overflow?
A stack overflow occurs when too many function calls or large local variables exhaust the fixed stack space, typically 1-8 MB. A heap overflow (or out-of-memory error) occurs when the program requests more heap memory than the operating system can provide. Stack overflow is usually caused by logic errors like infinite recursion, while heap overflow is caused by allocating too much data.
Do garbage-collected languages like Python and JavaScript use stack memory?
Yes. Even in garbage-collected languages, the call stack uses stack memory for function frames and local primitive variables. Objects, arrays, and strings are allocated on the heap. The garbage collector manages heap memory but does not touch stack memory, which is automatically managed by the function call mechanism.