Intermediate · Dynamic memory · topic 26 of 60 · 25 min
Stack and heap
Explanation
The memory layout of a process
high addresses
┌──────────────────────────┐
│ stack │ local variables, function call frames; grows DOWN
│ ↓ │
│ │
│ ↑ │
│ heap │ malloc / calloc / realloc; grows UP
├──────────────────────────┤
│ .bss │ globals and statics without an initialiser (zeroed)
│ .data │ globals and statics with an initialiser
│ .rodata / .text │ string literals, constants and the program's machine code
└──────────────────────────┘
low addressesAutomatic storage: the stack
Every function call pushes a frame on the stack with its parameters and local variables; returning pops it. This is extremely fast and automatic, but it has two limits: the size must usually be known at compile time, and the data dies when the function returns. The stack is also small (often 8 MB on Linux, 1 MB on Windows by default), so huge local arrays (int big[10000000];) crash with a stack overflow.
Dynamic storage: the heap
The heap is a large pool of memory managed by the C library. You ask for a block of a given size at run time with malloc, get a pointer to it, use it for as long as you like (even after the function that created it returns), and give it back with free. Nothing is automatic: forgetting free leaks memory, and using memory after free is undefined behaviour.
int *make_scores(int n) {
int *scores = malloc(n * sizeof *scores); /* n known only at run time */
if (scores == NULL) return NULL; /* allocation can fail */
for (int i = 0; i < n; i++) scores[i] = 0;
return scores; /* fine: heap memory outlives the function */
}
int main(void) {
int n = 5;
int *s = make_scores(n);
if (!s) return 1;
s[2] = 91;
free(s); /* give it back */
s = NULL;
return 0;
}| Stack | Heap | |
|---|---|---|
| Allocated by | Automatically on function call | You, with malloc/calloc/realloc |
| Freed by | Automatically on return | You, with free |
| Size | Known at compile time (mostly), small total | Decided at run time, large total |
| Speed | Very fast | Slower (bookkeeping) |
| Typical bugs | Stack overflow, returning &local | Leaks, use-after-free, double free |
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Stack and heap · 1/6
In this lesson you will see where a C program keeps its data.
Prefer a video by a teacher? Find free videos on “c memory layout stack vs heap explained malloc” on YouTube ↗
In real life: Loading a variable number of orders
A warehouse tool reads a file whose first line says how many orders follow (it might be 10 or 200,000). The program cannot know this when compiled, so it allocates exactly the right array on the heap after reading the count, and frees it when done.
int count;
if (fscanf(fp, "%d", &count) != 1 || count <= 0) return 1;
long *amounts = malloc((size_t) count * sizeof *amounts);
if (!amounts) { perror("malloc"); return 1; }
for (int i = 0; i < count; i++) fscanf(fp, "%ld", &amounts[i]);
/* … process … */
free(amounts);Practice (0/3 done)
Where does a local variable int count = 0; inside a function live?
Why can a function safely return a pointer from malloc but not &local?
Write a program that asks how many students there are (n), allocates an int array of n marks on the heap with malloc (checking for NULL), reads the marks, prints the average, and frees the array. Then try declaring int big[20000000]; as a local in main and observe what happens; explain it.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- malloc, calloc and freeDynamic memory · same module
- realloc and growing arraysDynamic memory · same module
- Memory leaks and other heap bugsDynamic memory · same module
- Memory 101: the stack and the heapRust Programming · Ownership: Rust's big idea
- Pointers, the stack and the heapC++ Programming (modern C++ and DSA) · References, pointers, arrays and strings
- JVM memory and garbage collectionJava Programming (Core to Spring Boot) · Design patterns, JVM internals and interviews
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which region grows as you call more nested functions?
Answer: Stack
Each call pushes a frame.
Who frees heap memory in C?
Answer: The program, by calling free
There is no garbage collector.
Where do uninitialised global variables live?
Answer: .bss (zero-initialised)
They start as zero.
A program declares a 400 MB local array and crashes at start. Why?
Answer: Stack overflow: the stack is much smaller
Use malloc for large data.
How does Rust decide when to free heap memory?Related
Answer: Ownership rules let the compiler insert the free at the right point
Rust frees a value when its owner goes out of scope, decided at compile time.
How long does a static local variable live?Related
Which memory is cleaned up automatically when a function returns?Related
Answer: The function's local variables on the stack
Stack variables are destroyed at the end of their scope; heap memory stays until deleted.
What does malloc return when it cannot allocate?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “Dynamic memory” before its exam: malloc, calloc and free, realloc and growing arrays, Memory leaks and other heap bugs, Dynamic strings and 2D arrays.
- Module 6 exam: Dynamic memory · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Structs, unions, enums and files. 60 topics left in the course before the final exam.
← Previous: NULL, dangling pointers and pointers to pointers