본문으로 건너뛰기
Previous
Next
C++ Stack vs Heap — Complete Guide

C++ Stack vs Heap — Complete Guide

C++ Stack vs Heap — Complete Guide

이 글의 핵심

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 limitstack overflow. (The cache array is unused in logic—it illustrates per-frame stack cost.)

// 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:

  1. Logic bug? → not here
  2. Leak? → Valgrind says no
  3. 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

  1. Process memory layout
  2. Stack memory
  3. Heap memory
  4. Stack vs heap performance
  5. Selection guide
  6. Complete examples
  7. Common memory errors
  8. Debugging tips
  9. 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.

// 실행 예제
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
RegionRoleLifetime
StackLocals, args, return addressesUntil scope returns
Heapnew / mallocUntil 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:

  1. Fast—just move the stack pointer
  2. Automatic—destroyed on scope exit
  3. Cache-friendly—contiguous Disadvantages:
  4. Small—don’t put megabytes as int huge[1000000] local
  5. 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

  1. Stack overflow — huge locals / deep recursion
  2. Dangling pointers — address of stack local returned
  3. delete on stack memory — undefined
  4. Double free / use-after-free
  5. Leaknew without delete on 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 pointerUB.

  • Memory leaks
  • Smart pointers
  • RAII

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

  • Stack vs heap (alternate slug)
  • Valgrind

같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.

  • [C++ Memory Leaks](/en/blog/cpp-series-06-2-memory-leak/
  • [Rust Memory Safety: Ownership, Borrowing, Lifetimes, unsafe](/en/blog/cpp-series-47-3-rust-memory-safety/
  • [Rust Ownership | Ownership, Borrowing, and Lifetimes](/en/blog/rust-series-02-ownership/
  • [Python Data Types | Lists· Dictionaries](/en/blog/python-series-03-data-types/
  • [C++ Memory Management: new/delete, Stack vs Heap, and RAII](/en/blog/cpp-memory-management-deep/

이 글에서 다루는 키워드 (관련 검색어)

C++, Memory Management, Stack, Heap, Pointer, Memory Layout, Valgrind 등으로 검색하시면 이 글이 도움이 됩니다.