Skip to content

Stack & Heap


Task: Watch what survives when a function returns

STACKHEAPStudentmain()aframes leave in the reverse order they arrived

Why Do We Need Stack and Heap?

In the previous chapter, we learned that a running program needs memory to store the data it works with.

But memory is not used as one undivided space.

Programs organize memory into different regions, each designed for a different purpose.

Two of the most important regions are:

  • Stack
  • Heap

Understanding them helps explain questions such as:

  • Where are local variables stored?
  • What happens when a function is called?
  • Why does recursion use the stack?
  • Where are dynamically created objects stored?
  • Why can a program run out of stack space?
  • Why does memory sometimes need to be managed automatically?

You do not need to understand operating-system internals to use the stack and heap.

You need a clear mental model of what they are used for and how their lifetimes differ.


The Big Picture

Think of a running program as having different areas of memory:

For this chapter, focus on two:

Code
Stack  function calls and their local dataHeap   dynamically allocated data

This is a simplified model. The exact memory layout depends on the programming language, compiler, runtime, and operating system. But this model is extremely useful when learning programming and DSA.


What Is the Stack?

Definition

The stack is a region of memory used to manage function calls and their associated data.

When a function is called, the program creates a stack frame for that call. When the function finishes, that frame is removed.

Consider:

Code
void greet() {    int age = 25;}

When greet() runs, the program needs space for information associated with that function call.

Code
Stack                      Stack          greet() frame                             age = 25                                             while it runs            after it finishes

The function's stack frame is no longer needed.


Stack Frames

A stack frame is the memory associated with one active function call.

It can contain information such as:

  • local variables
  • function parameters
  • return information
  • other execution-related data

Consider:

Code
void add(int a, int b) {    int result = a + b;} add(10, 20);

When add() is called, conceptually:

Code
Stack  add()                a = 10               b = 20               result = 30         

When the function returns, its frame is removed.

This is why the stack naturally follows the last-in, first-out (LIFO) principle.


Why Is It Called a Stack?

Imagine a stack of books. You place one book on top:

Code
  C    B    A  

To remove a book, you take the top one first.

The stack used by a program follows the same basic idea. If A starts, then B, then C, the most recently created frame belongs to C. When C finishes, B continues; when B finishes, A continues.

This is why nested function calls naturally fit the stack.


Function Calls and the Stack

Consider:

Code
void first() {    second();} void second() {    third();} void third() {    int x = 10;}

As each call begins, its frame goes on top:

Code
       first()       second()      third()                          first()       second()                                                      first()                                   

When third() finishes, its frame disappears first, then second(), then first().

This is the fundamental reason function calls are managed using a stack.


Recursion and the Stack

This becomes especially important with recursion.

Code
void count(int n) {    if (n == 0) return;     System.out.println(n);    count(n - 1);}

Calling count(3) creates a sequence of function calls, and each call needs its own stack frame:

Code
count(3)  count(2)  count(1)  count(0) Stack  count(0)   count(1)   count(2)   count(3)  

Once the base case is reached, the calls return one by one and the frames are removed.

This is why recursion consumes stack memory.


Stack Overflow

The stack has a limited amount of space.

If a program creates too many nested function calls, the stack can become full. This is called a stack overflow.

Code
void forever() {    forever();}

There is no stopping condition. The calls keep accumulating until the available stack space is exhausted, and the program fails with a stack overflow error.

Note

Recursion is not automatically bad.

The problem occurs when the number of active calls becomes too large for the available stack space.


What Is the Heap?

Definition

The heap is a region of memory used for dynamically allocated data whose lifetime is not tied directly to a single function call.

Objects and other dynamically created data are commonly stored in the heap.

For example:

Code
Student student = new Student();

The variable student is associated with the current function's execution, while the object created with new lives in dynamically allocated memory.

The exact details depend on the language and runtime, but this distinction is extremely useful.


Why Do We Need the Heap?

Imagine a function creates an object that needs to continue existing beyond the function's local execution.

A function's stack frame disappears when the function returns. So data that needs a longer or independently managed lifetime cannot simply depend on that frame.

The heap provides memory for dynamically allocated data.

Code
Student createStudent() {    Student s = new Student();    return s;}

The object can continue to exist even though the function that created it has finished. The animation at the top of this page walks through exactly this: the frame appears, allocates, returns and is removed, and the object stays where it was.


Stack vs Heap

The simplest comparison is:

StackHeap
Manages function callsStores dynamically allocated data
Uses stack framesUses dynamically allocated memory
Naturally follows LIFODoes not follow LIFO
Local execution data is commonly stored hereObjects and dynamic data are commonly stored here
Frames are removed when calls returnData remains until it is no longer needed and reclaimed
Usually faster to allocate and releaseGenerally more flexible
Limited in sizeUsually much larger

One important point: "Stack is fast and heap is slow" is an oversimplification. The actual performance depends on the language, runtime, allocation strategy, hardware, and access pattern.

The more useful distinction is:

The stack is organized around function execution; the heap is organized around dynamically allocated data and its lifetime.


A Function Using Both

Consider:

Code
void process() {    int count = 10;    Student student = new Student();}

A simplified mental model is:

Code
Stack  process()            count = 10           student                                    Heap                                             Student                               object                               

The function call and its local execution data are associated with the stack. The dynamically created object is associated with the heap.

This distinction becomes particularly useful when we study references and pointers.


Who Cleans Up the Heap?

This depends on the programming language.

Some languages require programmers to explicitly manage dynamically allocated memory. For example, in C++:

Code
Student* s = new Student(); delete s;

The programmer is responsible for releasing the allocated memory.

Languages such as Java and Python use garbage collection to automatically reclaim heap memory that is no longer reachable by the program.

Code
Object is no longer reachable                   Garbage collector                    Memory reclaimed

This does not mean garbage-collected languages never have memory problems. A program can still keep unnecessary objects reachable and consume excessive memory.


Stack and Heap in Different Languages

The stack/heap model is useful across many languages, but the exact implementation differs.

C / C++ give programmers more direct control over memory allocation.

Code
int x = 10;int* p = new int(20); delete p;

Java allocates objects created with new on the heap in the usual conceptual model, while local variables and references are associated with stack frames. Java's garbage collector manages heap memory.

Python is more abstract. Objects are managed by the Python runtime, and implementation details such as CPython's memory management do not map perfectly onto the simple "everything is either stack or heap" model.

So do not assume that every language follows the simplified model identically.


Common Misconceptions

Watch out

"Every local variable is always stored on the stack." Not necessarily. The stack/heap model is a useful conceptual model, but compilers and runtimes can optimize how values are stored.

"Everything created with new is always on the heap in every language." Not universally. The exact behavior depends on the language and runtime.

"Heap memory is infinite." No. Heap memory is also limited. Excessive allocation can eventually cause memory exhaustion.

"Garbage collection immediately deletes unused objects." No. Garbage collection happens according to the runtime's own strategy. An object that is no longer needed may remain in memory until the runtime reclaims it.

"Stack memory is always faster than heap memory." This is too simplistic. Allocation patterns, caching, compiler optimizations, and runtime behavior all affect performance.


Stack vs Heap: The Mental Model

If you remember only one picture from this chapter, remember this:

Code
                Running Program                                                                        STACK                    HEAP                                    Function calls          Dynamic data   Stack frames            Objects   Local execution         Longer-lived data   parameters              Dynamic allocation

The stack answers:

"What is currently happening in my function calls?"

The heap answers:

"Where can dynamically allocated data live independently of a particular function call?"

This mental model will be enough for most of the DSA you will study.


Quick Check

  1. What is a stack frame?
  2. Why are function calls naturally managed using a stack?
  3. Why does recursion consume stack memory?
  4. What causes a stack overflow?
  5. What is the heap used for?
  6. Why can an object outlive the function that created it?
  7. What is the main conceptual difference between stack and heap?
  8. Does every programming language implement stack and heap exactly the same way?

Quick Recap

  • The stack manages active function calls.
  • Each function call gets a stack frame.
  • Stack frames are removed when their function calls return.
  • Recursion creates multiple active stack frames.
  • Too many active calls can cause a stack overflow.
  • The heap provides memory for dynamically allocated data.
  • Heap data can have a lifetime independent of a particular function call.
  • Memory management differs between languages.
  • Garbage-collected languages automatically reclaim unreachable heap objects.
  • Stack and heap are useful mental models, but actual implementations can be more complex.

Where This Leads

We now know:

Code
Memory   Stack & Heap   Different places for different kinds of data

But one important question remains:

How does one piece of data refer to another location in memory?

That is where pointers and references come in. They are the mechanism behind many of the structures you will soon encounter: linked lists, trees, graphs and hash tables.

Understanding them will make those data structures much easier to visualize.

Key takeaway

The stack organizes memory around active function calls, while the heap provides memory for dynamically allocated data. The difference between their organization and lifetime is fundamental to understanding recursion, objects, references, and many data structures.