Skip to content

Intermediate · Dynamic memory · topic 26 of 60 · 25 min

Stack and heap

Explanation

A running C program's memory has regions: code (text), global and static data, the heap and the stack. Local variables live on the stack and disappear when their function returns. The heap holds memory you request at run time with malloc; it stays until you free it. Use the heap when the size is known only at run time or the data must outlive the function.

The memory layout of a process

output
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 addresses
A simplified picture of a typical Linux process (details vary by system).

Automatic 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.

c
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;
}
StackHeap
Allocated byAutomatically on function callYou, with malloc/calloc/realloc
Freed byAutomatically on returnYou, with free
SizeKnown at compile time (mostly), small totalDecided at run time, large total
SpeedVery fastSlower (bookkeeping)
Typical bugsStack overflow, returning &localLeaks, use-after-free, double free
Careful: Variable-length arrays (C99: int a[n];) put a run-time-sized array on the stack. A large or untrusted n can silently overflow the stack, so many coding standards forbid VLAs (and they are optional since C11). For sizes that come from input, use malloc and check the result.
Think of it like this: The stack is like the plates at a buffet counter: taken and returned in order, automatically cleared as each course ends. The heap is like renting a storage locker: you choose the size, it stays yours until you hand back the key (free), and if you forget, you keep paying (a leak).
Tip: Default to automatic (stack) variables. Reach for the heap only when you need run-time sizes, large data, or data that must outlive a function.

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

Stack and heap

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.

c
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)

Task 1 · Question

Where does a local variable int count = 0; inside a function live?

Task 2 · Question

Why can a function safely return a pointer from malloc but not &local?

Task 3 · Practice

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

Question 1

1.Which region grows as you call more nested functions?

Question 2

2.Who frees heap memory in C?

Question 3

3.Where do uninitialised global variables live?

Question 4

4.A program declares a 400 MB local array and crashes at start. Why?

Read more (free)

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.

From Memory 101: the stack and the heap

How long does a static local variable live?Related

Answer: The whole program run

Static storage duration.

From Scope and storage classes

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.

From Pointers, the stack and the heap

What does malloc return when it cannot allocate?Related

Answer: NULL

Always check.

From malloc, calloc and free

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

  1. 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.
  2. Module 6 exam: Dynamic memory · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. 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