Stack vs Heap
Side-by-Side Comparison
Aspect | Stack | Heap |
|---|---|---|
Allocation speed | Extremely fast -- just moves a pointer | Slower -- involves an allocator searching for free space |
Size limits | Small and fixed per thread (often a few MB) | Large -- limited mainly by available system memory |
Lifetime | Tied to the enclosing function/block; ends automatically on return | Lasts until you explicitly call |
Who manages it | The compiler, automatically | You, the programmer, manually |
Management style | Automatic (no code needed) | Manual ( |
Typical contents | Local variables, function parameters | Data whose size or lifetime is not known until runtime |
Risk if misused | Stack overflow (too much data or too-deep recursion) | Leaks, dangling pointers, double frees |
The Stack: Fast, Automatic, Limited
#include <stdio.h>
int square(int n) {
int result = n * n; // 'result' and 'n' live on the stack
return result;
} // stack frame for square() is popped automatically here
int main(void) {
int value = square(5); // 'value' also lives on the stack
printf("%d\n", value);
return 0;
} // main()'s stack frame is popped hereThe tradeoff is that stack space is limited and its lifetime is rigid: a stack variable disappears the instant its function returns, and you cannot resize it or make it outlive its scope. Allocating a very large array on the stack, or recursing too deeply, can exhaust the stack entirely and crash the program.
void risky(void) {
int huge[10000000]; // ~40MB on the stack -- likely to overflow
huge[0] = 1;
}The Heap: Flexible, Manual, Persistent
malloc(), calloc(), or realloc(). Unlike stack memory, heap memory does not disappear when the function that allocated it returns — it persists until you explicitly release it with free(). That makes the heap the right place for data whose size is only known at runtime, or that needs to outlive the function that created it.#include <stdio.h>
#include <stdlib.h>
int *make_array(int n) {
int *arr = malloc(n * sizeof(int)); // lives on the HEAP
if (arr == NULL) {
return NULL;
}
for (int i = 0; i < n; i++) {
arr[i] = i * i;
}
return arr; // safe to return -- this memory outlives make_array()
}
int main(void) {
int *nums = make_array(5);
if (nums == NULL) {
return 1;
}
for (int i = 0; i < 5; i++) {
printf("%d\n", nums[i]);
}
free(nums); // your responsibility -- the heap never cleans up for you
return 0;
}Choosing Between Them
Use the stack for small, short-lived data whose size is known at compile time -- it is faster and requires no cleanup code
Use the heap when the size is only known at runtime, when the data is large, or when it must outlive the function that created it
Use the heap when you need to explicitly control when memory is released, independent of function call boundaries
Prefer the stack by default -- reach for the heap only when the stack genuinely cannot do the job