Why do some values vanish when a function returns while others stay behind? Notes on your desk get cleared away when the task ends; a box you put in the storeroom stays until someone asks for it.
Program memory splits into two regions, and the difference comes down to "when does it disappear" and "is the size known in advance". Get this right and three things click at once: why some values vanish when a function returns, why passing a huge object is cheap, and why memory problems almost always live in the heap.
Every call pushes a frame holding three things: parameters, the function's locals, and the return address. The size is fixed at compile time, which makes allocation nearly free — move a pointer up to allocate, down to release.
Arrays, objects and strings whose size is decided at run time, or which must outlive the call, live on the heap: a big warehouse that hands out free space on demand. Finding and managing that space costs more than the stack.
When a function returns its frame vanishes along with its locals — but a heap object survives as long as something holds its address. Watch login's frame disappear below while the User object stays.
Passing an array copies the tag, not the array, so a million-element array costs the same as copying one number. The side effect: mutating it inside the function changes it outside too — same box.
Deep calls stack up, and endless recursion overflows the limit. The heap instead suffers from boxes nobody uses piling up — which is the next chapter. Watch the stack grow three frames deep and shrink while heap boxes remain.
1main() {2 user = login("danbi")PC ◀3 cart = ["book"]4 total = checkout(user, cart)5 print(total)6}7login(name) {8 return User(name)9}10checkout(u, items) {11 sum = 012 for it in items: sum += price(it)13 return sum14}15price(it) { return 12000 }
main starts and a frame is placed on the stack, with slots for its locals (user, cart, total).
Try it in the simulator
Terms in this chapter
Why it evolved this way
Why two regions? With only a stack there is nowhere for data that must outlive a call; with only a heap every local variable would require a warehouse lookup. Short-lived fixed-size data on a blazing-fast stack, large long-lived data on a flexible heap — that division is near-universal across languages.
The stack dies with the function; the heap lives as long as something points at it.
The remaining problem
So who cleans up the heap boxes, and when? →