[2026] C++ Stack vs Heap | Why Recursion Crashes and Real Stack Overflow Cases
이 글의 핵심
C++ stack vs heap: stack overflow from deep recursion and huge locals, memory layout, performance, new/delete, smart pointer lead-in—Valgrind and ASan-friendly mental model.
Introduction: Crashed by stack overflow
Why the process died — recursion trap
You implemented Fibonacci recursively. n = 10 worked; n = 100000 killed the process with no helpful message. The stack is a small, fast region—like a narrow workbench: deep recursion stacks many frames, each holding locals, until the bench overflows.
The demo below stacks ~4KB per call (int cache[1000]) and explores two branches—stack usage explodes. fibonacci(100000) exceeds the process’s stack limit → stack overflow. (The cache array is unused in logic—it illustrates per-frame stack cost.)
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// g++ -std=c++17 -o fib fib.cpp && ./fib
#include <iostream>
// 변수 선언 및 초기화
int fibonacci(int n) {
int cache[1000]; // ~4KB per frame
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main() {
std::cout << fibonacci(100000); // crashes — stack overflow
return 0;
}
Debugging path:
- Logic bug? → not here
- Leak? → Valgrind says no
- Stack overflow — stack limit exceeded Takeaway: know stack vs heap; huge locals and deep recursion are dangerous on the default stack. After reading:
- How stack and heap behave
- How to avoid stack overflow
- When to use stack vs heap
- How layout fits later smart pointers and RAII Previous: Compilation process
Table of contents
- Process memory layout
- Stack memory
- Heap memory
- Stack vs heap performance
- Selection guide
- Complete examples
- Common memory errors
- Debugging tips
- Production patterns
1. C++ process memory (simplified)
The OS maps text (code), data/BSS (globals), heap (grows up), and stack (grows down). If stack and heap meet, you’re in trouble. 아래 코드는 mermaid를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
flowchart TB
subgraph addr["Address direction (low → high)"]
direction TB
T[Text code]
D[Global/static Data, BSS]
H[Heap ↑]
free[Free space]
S[Stack ↓]
end
T --> D --> H --> free --> S
style H fill:#e1f5fe
style S fill:#fff3e0
| Region | Role | Lifetime |
|---|---|---|
| Stack | Locals, args, return addresses | Until scope returns |
| Heap | new / malloc | Until freed or process exit |
| Why stacks are small: one stack per thread; deep recursion and large frames consume it quickly—typically ~1–8MB per platform default. |
2. Stack memory
Fast, automatic, limited. Each function call pushes a stack frame (locals, saved state). Advantages:
- Fast—just move the stack pointer
- Automatic—destroyed on scope exit
- Cache-friendly—contiguous Disadvantages:
- Small—don’t put megabytes as
int huge[1000000]local - Lifetime tied to scope—returning address of a local → dangling pointer
Stack overflow examples
Huge local array → use std::vector on the heap. Deep recursion with big locals → reduce depth, move arrays to heap, or iterate. Mitigation (last resort):
ulimit -s 16384 # Linux: 16MB (example)
Root fix: don’t rely on giant stacks—heap or iteration.
3. Heap memory
Flexible size and lifetime; you (or smart pointers) must free it.
Pros: large allocations, outliving scope, polymorphic arrays
Cons: slower, fragmentation risk, manual correctness without RAII
4. Stack vs heap performance
Microbenchmarks often show stack allocation ~orders of magnitude faster than new/delete in tight loops—don’t micro-optimize hot loops with per-iteration heap allocs.
5. Selection guide
- Small, local, short-lived → stack
- Large, shared, runtime-sized, polymorphic → heap +
vector/unique_ptr
6. Patterns
- unique_ptr for sole ownership
- shared_ptr when shared (watch cycles → weak_ptr)
- RAII wrappers for buffers and files
7. Common errors
- Stack overflow — huge locals / deep recursion
- Dangling pointers — address of stack local returned
deleteon stack memory — undefined- Double free / use-after-free
- Leak —
newwithoutdeleteon all paths
8. Debugging tips
- Valgrind / ASan (
-fsanitize=address) for heap corruption and leaks - GDB + core for post-mortem stack traces
- ulimit -s to inspect stack limit
9. Production patterns
- Object pools to cut repeated
new/delete - Stack allocators / arenas for frame-scoped bump allocation
- Default to unique_ptr, shared_ptr only when needed
FAQ
Biggest difference stack vs heap?
A. Stack auto-managed, tiny, fast; heap flexible and large but manual (or smart pointers).
How to prevent stack overflow?
A. Avoid huge stack arrays; limit recursion depth; use heap containers; iterate.
Stack vs heap speed?
A. Microbenchmarks often show 50–100× gap for raw alloc vs stack pointer bump—measure your workload.
Why not return address of stack variable?
A. After return the frame is gone—dangling pointer → UB.
Related posts
Keywords
C++ stack vs heap, stack overflow, memory layout, dangling pointer, heap allocation, recursion
Summary
- Stack: fast, automatic, limited
- Heap: flexible, must manage (prefer smart pointers)
- Default: small locals on stack; large data on heap
- Watch recursion and large arrays on the stack Next: Memory leaks #6-2
References
Practical tips
Debugging
- Enable warnings; reproduce minimally
Performance
- Profile before optimizing