C fundamentals · lesson 05

Stack vs heap

Two regions of memory, two completely different rules. Understanding which one you're in — and why — is the foundation of everything that follows.

in progress
12 min interactive

The confusion

You declare a variable and it works. You call malloc() and it works. Both give you memory. So why are they different things?

Because they have completely different lifetimes, sizes, and ownership rules. Confuse them and you get memory leaks, dangling pointers, and stack overflows. Understand them and the rest of C becomes predictable.

💡
Mental model: the stack is a pile of trays in a cafeteria — you add a tray, you remove a tray, always from the top, automatically. The heap is a storage room — you walk in, take a box, and you are personally responsible for returning it.

The stack

Every local variable you declare lives on the stack. When you call a function, the CPU pushes a new frame onto the stack. When that function returns, the frame is popped and the memory is automatically reclaimed. You never free it. You can't forget to free it. It's not your job.

The trade-off: the stack is fixed-size. On most Linux systems, 8 MB by default. Declare a 10 MB array on the stack and your program crashes immediately — a stack overflow.

c
// all of these live on the stack void some_function() { int x = 42; // 4 bytes double pi = 3.14159; // 8 bytes char buf[64]; // 64 bytes // when this function returns, x, pi, and buf // are all gone. automatically. no free() needed. }

The heap

The heap is where you go when you need memory that outlives the current function, or when you don't know the size at compile time. You request it with malloc(). You release it with free(). If you forget the free(), that memory is gone for the lifetime of your program — a memory leak.

⚠️
Common mistake: after calling free(ptr), the pointer variable still holds the old address. Reading from it is undefined behavior. Set it to NULL immediately after freeing.
c
int *ptr = malloc(5 * sizeof(int)); // 20 bytes on the heap if (ptr == NULL) { // malloc failed — always check! return -1; } for (int i = 0; i < 5; i++) { ptr[i] = i * 10; } free(ptr); // ✓ released ptr = NULL; // ✓ no dangling pointer

Watch it happen

Step through the visualization below. Watch the heap blocks appear and disappear. Notice what happens to the stack pointer variable when the heap block is freed.

heap & stack — live allocation
Click next to start the walkthrough.

The rules

stack
  • Automatic — no malloc, no free
  • Limited size (~8 MB)
  • Fast allocation (move a register)
  • Lifetime = function scope
  • Local variables, function args
heap
  • Manual — you malloc, you free
  • Limited only by RAM
  • Slower (syscall, bookkeeping)
  • Lifetime = until you free it
  • Dynamic sizes, long-lived data
🚫
Returning a pointer to a stack variable is one of the most common bugs in C. The function returns, the stack frame is destroyed, and the caller holds a pointer to garbage. The compiler will warn you — listen to the warning.
one-line takeaway

Stack memory manages itself. Heap memory does exactly what you tell it — nothing more.