Runtime · intermediate

Stack vs heap memory

In common runtime models, stack storage supports active calls with scoped, last-in-first-out allocation, while heap storage supports dynamically allocated objects whose lifetimes and allocation order need not follow call nesting. Exact placement and management are implementation- and language-dependent.

Why it matters

The distinction explains recursive depth, object lifetime, allocation costs, garbage collection, manual deallocation, and why a local variable can refer to an object that outlives the call.

Mental model

How to reason about stack vs heap memory

A thread's stack efficiently tracks nested execution, while a heap allocator manages independently lived blocks or objects shared across calls and sometimes threads. A stack slot can contain a reference to a heap object; value category does not by itself prove physical location.

Analogy

Stack storage is a pile of trays removed in reverse order; heap storage is a warehouse where items have independent tickets and can leave in an order unrelated to arrival.

Examples

See the boundary, not just the happy path

Worked example · Local reference and heap object

void f() { var user = User('Ada'); }

In a managed runtime, the local binding can live in frame state while the User object is managed separately. Escape analysis may optimize the physical allocation, so the language-level code alone does not guarantee an address region.

Worked example · Dynamic lifetime in C

int *items = malloc(count * sizeof *items); /* ... */ free(items);

malloc obtains a dynamically managed block whose lifetime continues until free, independent of the allocating function's return. The pointer variable and the allocated block are separate entities.

Useful contrast · Semantic lifetime versus physical placement

A compiler can eliminate an allocation that does not escape

Optimizers may scalar-replace or stack-allocate an object while preserving language semantics. Stack and heap are useful runtime models, not always source-level promises.

Common mistakes

Misconceptions to remove early

Saying value types are always on the stack

A value can be a field of a heap object, captured state, boxed data, or optimized into registers. Type semantics and storage location are different questions.

Assuming heap memory is process-global unstructured storage

Allocators and managed runtimes track object boundaries, ownership, reachability, arenas, generations, or thread-local caches. The implementation is structured even when lifetime is not LIFO.

Quick check

Can you predict the result?

1. Can a stack-frame local variable refer to an object with heap-managed lifetime?
  • Yes; the local can hold a reference while the object is managed separately.
  • No; stack frames can contain only whole objects.
  • Only if the object is also a network socket.
Answer: Yes; the local can hold a reference while the object is managed separately.
2. Why can source code alone be insufficient to prove physical stack or heap placement?
Answer: Language abstractions and compiler optimizations can preserve behavior while changing or eliminating allocations.

Keep building

Authoritative references

Make the idea retrievable.

Study this concept with spaced repetition, next to the commands where you use it.

Get Terminaster