Stack vs Heap Memory
Understanding where and how memory is allocated is crucial for writing efficient C++ programs. See the differences in action:
Stack vs Heap Memory
Stack (LIFO)
Stack Memory↓ grows down
High Address ↑
main()
32 bytes
int x = 42
4 bytes
Low Address ↓
Stack Usage:36 bytes
Automatic deallocation on scope exit
Heap (Dynamic)
Heap Memory↑ grows up
Low Address ↓
new[]
0x55a1100
40 bytes
High Address ↑
Heap Usage:40 bytes
Fragmentation:0.0%
| Aspect | Stack | Heap |
|---|---|---|
| Allocation | Automatic | Manual (new/malloc) |
| Deallocation | Automatic | Manual (delete/free) |
| Speed | Very Fast | Slower |
| Size Limit | Limited (~8MB) | System Memory |
| Fragmentation | None | Possible |
Stack Memory
Characteristics
- Automatic: Managed by compiler
- Fast: Simple pointer arithmetic
- Limited: ~8MB default size
- LIFO: Last In, First Out
- Scope-based: Automatic cleanup
Stack Allocation
void function() { int local = 42; // Stack char buffer[256]; // Stack MyClass obj; // Stack } // All automatically deallocated
Stack Frame
Each function call creates a frame:
[Return Address] [Previous Frame Pointer] [Local Variables] [Function Parameters]
Heap Memory
Characteristics
- Manual: You control lifetime
- Slower: Allocation overhead
- Large: System memory limit
- Fragmented: Can have gaps
- Flexible: Any size, any time
Heap Allocation
// C++ style int* ptr = new int(42); int* arr = new int[100]; delete ptr; delete[] arr; // C style int* ptr = (int*)malloc(sizeof(int)); free(ptr); // Smart pointers (recommended) auto ptr = std::make_unique<int>(42); auto arr = std::make_shared<int[]>(100);
Memory Issues
Stack Overflow
// Recursive without base case void infinite() { infinite(); } // Large local arrays void bad() { int huge[10000000]; // Too big! }
Memory Leak
void leak() { int* p = new int(42); // Missing: delete p; } // Memory leaked!
Dangling Pointer
int* dangling() { int local = 42; return &local; // Bad! Returns stack address }
Comparison Table
| Aspect | Stack | Heap |
|---|---|---|
| Speed | Very Fast | Slower |
| Size | Limited (~8MB) | System Memory |
| Management | Automatic | Manual |
| Fragmentation | None | Possible |
| Thread Safety | Yes (per thread) | No (needs sync) |
| Allocation | Compile-time size | Runtime size |
Best Practices
- Prefer stack allocation when possible
- Use smart pointers for heap objects
- Follow RAII principles
- Avoid large stack arrays (use std::vector)
- Match new/delete and new[]/delete[]
- Check for null before dereferencing
- Use tools like valgrind, sanitizers
Modern C++ Approach
// Avoid raw pointers // Bad int* p = new int(42); // Good auto p = std::make_unique<int>(42); // Container instead of array // Bad int* arr = new int[size]; // Good std::vector<int> arr(size);
Next Steps
- Master Smart Pointers
- Learn RAII Patterns
- Explore Memory Layout
