Skip to main content

Stack vs Heap: Where Your Program Actually Keeps Its Stuff

Every variable you create has to live somewhere — and the address matters

Updated 7 min readMarkdown

To put it simply, every time your program creates a value — a number, a name, a list — it has to put that value somewhere in memory, and there are really only two neighbourhoods it can live in: the stack and the heap. The stack is small, fast, and tidy. The heap is big, flexible, and messy. Knowing which one your data lives in explains a surprising number of bugs, crashes, and slowdowns.

The question most beginners eventually ask is a simple one: where does a variable actually live? You write name = "Min" and it works, so you never think about it. But the computer has to store that string somewhere, and the choice it makes — stack or heap — decides how long the value survives, how fast you can reach it, and who is responsible for cleaning it up.

Think of it like a hotel and a storage warehouse. The stack is a hotel with a strict rule: guests check in and out in order, and the room is cleaned the moment you leave. The heap is a warehouse where you can rent any size of space for as long as you like — but you have to remember to give the space back, or it stays rented forever.

The stack is small, fast, and automatic

The stack stores the things your program knows about right now: function calls, local variables, and return addresses. Every time you call a function, the program pushes a little frame onto the stack — the function's variables live in that frame — and when the function returns, the frame is popped off and everything in it disappears. That is the whole point: the stack cleans itself up automatically.

The short version: the stack is a pile of plates — you can only take the top one off, and everything is tidy because the order is fixed.

That fixed order is what makes the stack fast. The computer always knows exactly where the next free spot is — the top — so putting something on the stack is almost free. But the order is also the limit. You cannot keep something on the stack after its function has finished, because the frame is gone. And the stack is small, usually a few megabytes, so if you push too much onto it, it overflows. That is literally what a "stack overflow" error means: the pile of plates got too tall and fell over.

Recursion is the classic way to see it. Every call adds another frame, and if the calls never stop, the stack runs out of room:

def count_down(n):
    print(n)
    return count_down(n - 1)  # never stops — each call adds a stack frame

count_down(5)

Each call to count_down pushes a new frame onto the stack, and because nothing ever returns, the frames keep piling up until Python gives up with a RecursionError. The stack is doing exactly what it is supposed to do — the bug is that the code never lets it unwind.

The heap is big, flexible, and your responsibility

The heap is where everything that needs to outlive a single function call goes. When you create a list, a dictionary, or an object, it usually lives on the heap. Your variable is just a small reference — an address — that points at it. The heap has no fixed order and no automatic cleanup in the same way: you can create things in any order, keep them for as long as you like, and hand references to them around between functions.

That flexibility is why the heap exists. A list that grows as the user adds items cannot live on the stack, because nobody knows how big it will get. An object that three different functions need to share cannot live in one function's frame, because the frame disappears when the function returns. The heap is the shared space where long-lived things live.

But flexibility has a cost. Finding a free spot in the heap takes work, because the free space is scattered. And something has to clean up. In Python and JavaScript, a garbage collector watches for heap objects nobody points to any more and frees them. In C and C++, you free the memory yourself — and forgetting to is how programs slowly eat all the memory and die, a problem called a memory leak.

Here is the smallest version that shows the difference. Watch what survives the function call:

def make_list():
    small = 5              # lives on the stack — gone when the function returns
    big = [1, 2, 3, 4, 5]  # lives on the heap — survives, because we return a reference
    return big

my_list = make_list()
print(my_list)  # [1, 2, 3, 4, 5] — the list is still there

The number 5 disappears with the function's frame. The list lives on, because make_list handed back a reference to it, and my_list now holds that reference. As long as something points at the heap object, it stays alive. The moment nothing points at it, the garbage collector is allowed to clean it up.

The two work together, not against each other

This is the part people miss: stack and heap are not rivals. Every real program uses both, all the time. Your function calls and local numbers sit on the stack, and the moment you create something bigger or longer-lived, a reference on the stack points to the real data on the heap. The stack is the index; the heap is the warehouse.

Put side by side, the difference is easy to see:

Stack Heap
Size Small, a few MB Large, limited by your RAM
Speed Very fast — just move the top Slower — must find free space
Lifetime Dies when the function returns Lives until nothing points to it
Cleanup Automatic, by popping frames Garbage collector, or you, by hand
Order Strict — last in, first out Any order, any size
Good for Function calls, small local values Lists, objects, anything shared or long-lived

The verdict is not a choice you usually make yourself — your language makes it for you, and it makes the right call most of the time. What matters is understanding the trade-off, because it explains the errors you will meet: stack overflow from runaway recursion, memory leaks from forgotten heap objects, and the strange bug where two variables seem to change each other because they point at the same heap object.

Takeaways:

  • The stack holds function calls and local values; it is fast, small, and cleans itself up
  • The heap holds lists, objects, and anything long-lived; it is big and flexible
  • A variable is often just a reference on the stack pointing at real data on the heap
  • Stack overflow means too many unfinished function calls piled up
  • Memory leaks happen when heap objects nobody needs are never freed
  • Two variables can point at the same heap object — change one, and the other sees it too

References and further reading

— Min SiThu Software Engineer & Tech Content Creator https://minsithu.org

About the author

  • Nubbad Developer. | Now I accidentally create problems.

No comments yet. Be the first to comment.