I will explain where your variables live in physical memory. The choice between Stack and Heap defines both the execution speed and the lifecycle of your C++ applications. Managing this partition is what makes systems programmers different from application programmers.
Let's look at the differences, allocations, and systems hazards of these two memory zones.
The Stack: Automatic and Ultra Fast
The stack is a contiguous region of memory managed automatically by the CPU's stack pointer. When a function is called, its local variables are pushed onto the stack. When the function returns, the stack pointer moves back, and all those variables are instantly discarded.
* Cafeteria Tray Metaphor: Stack memory is like a stack of cafeteria trays. You add trays to the top and remove them from the top (Last In, First Out). It is incredibly fast because allocating memory is just shifting a single pointer register, but you cannot request a dynamic amount of space at runtime.
The Heap: Large and Dynamic
The heap is a massive pool of memory managed by the operating system. You use the heap when you do not know how much memory you need at compile time (such as loading a file or a user variable size) or when you want variables to survive after a function exits.
To allocate memory on the heap, we use the new operator. To return it to the OS, we must use the delete operator:
Memory Leaks and Dangling Pointers
Because C++ has no garbage collector, you are manually responsible for every byte of heap memory you request. This leads to two legendary systems bugs:
1. Memory Leaks
If you allocate memory on the heap and lose the pointer storing its address without calling delete, that memory remains reserved. If this happens inside a loop, your program will slowly consume all your RAM until the operating system terminates it.
* The Storage Locker Metaphor: Heap memory is like renting a public storage locker. You can store whatever you want inside, but if you lose the key (lose the pointer), you cannot open the locker to empty it, yet you keep paying rent forever (a memory leak) until your credit card declines.
2. Dangling Pointers
If you call delete on a pointer, the memory is returned to the OS. However, the pointer variable still stores that old memory address! If you try to dereference or use that pointer again, you will corrupt memory or crash the program. Always set pointers to nullptr after deleting them.
Stack Overflow: Physics of the Stack
Because stack frames are stacked LIFO, the compiler must know the sizes of variables. The stack has a small, restricted size allocated by the operating system (typically between 1MB and 8MB).
If you attempt to allocate a massive static variable or trigger infinite function recursion, you run out of stack space entirely. The stack pointer pushes past the boundary line, resulting in a stack overflow crash:
Allocation Latency Benchmarks
Why not use the heap for everything? Because the stack is physically much faster. Allocating stack space is done in a fraction of a nanosecond with a single CPU instruction:
sub rsp, 16 ; Shifting the stack pointer down is instant
Heap allocation, however, requires a system call to the operating system memory allocator. The allocator must traverse lists of free blocks, locate an empty pocket of space, deal with thread locks, and map the memory, taking hundreds of nanoseconds. Always prioritize the stack for performance critical functions.
Smart Pointers (Safe Dynamic Memory)
Because manually calling new and delete is error prone, modern C++ introduces Smart Pointers (defined in the <memory> header). Smart pointers are class wrappers around raw heap pointers that automatically delete the managed memory when they exit scope using RAII.
The most common smart pointer is std::unique_ptr, which holds exclusive ownership of a heap resource: