Memory Management Complete Guide
Stack vs Heap Advanced Topic

C++ Dynamic Memory: Complete Guide to Stack vs Heap Memory

Master C++ dynamic memory with comprehensive examples of stack vs heap memory, new/delete operators, memory management, smart pointers, and practical applications. Learn efficient memory allocation techniques.

Stack Memory

Automatic allocation

Heap Memory

Dynamic allocation

Smart Pointers

Memory safety

Memory Leaks

Prevention & detection

C++ Tutorial · Dynamic Memory

Stack memory is automatic; heap memory is manual (or smart). Learn allocation, deallocation, leaks, and why RAII and smart pointers are the modern default.

C++ dynamic memory infographic: stack vs heap memory, new and delete operators, malloc free, smart pointers unique_ptr shared_ptr, and RAII
C++ dynamic memory guide — stack vs heap, new/delete, memory leaks, and smart pointers for safe modern C++ memory management.

What you will learn

  • Allocate with new/delete and new[]/delete[]
  • Pair every new with exactly one delete
  • Spot memory leaks and double-delete bugs
  • Introduce unique_ptr and shared_ptr basics
  • Apply RAII so destructors free resources

Why this topic matters

Memory questions dominate C++ interviews. Employers expect you to prefer smart pointers over raw new/delete in new code.

Key terms & indexing

C++ new delete dynamic memory C++ smart pointers C++ RAII C++

Understanding Memory in C++

C++ provides two main types of memory: stack and heap. Understanding the difference between them is crucial for writing efficient, safe, and correct C++ programs. Dynamic memory management allows programs to allocate memory at runtime, providing flexibility but also requiring careful management.

Memory Layout in C++ Program
Stack Memory
0x7fff5fbff8ac
localVar = 42
0x7fff5fbff8b0
temp = 3.14
0x7fff5fbff8b8
buffer[10]

Fast, automatic, LIFO structure

Heap Memory
0x100400000
new int[100]
0x100400190
new Object()
0x100400200
malloc(500)
0x100400400
Dynamic Data

Flexible, manual management, global access

Stack Memory
  • Allocation: Automatic
  • Speed: Very Fast
  • Size: Limited (MBs)
  • Lifetime: Function scope
  • Management: Compiler
Heap Memory
  • Allocation: Manual
  • Speed: Slower
  • Size: Large (GBs)
  • Lifetime: Programmer controlled
  • Management: Programmer
Smart Pointers
  • Allocation: Automatic
  • Speed: Fast
  • Safety: High
  • Lifetime: RAII controlled
  • Management: Automatic
Key Concepts:
  • Stack: Automatic, fast, limited size, function-scoped variables
  • Heap: Manual, flexible, large size, programmer-controlled lifetime
  • Dynamic Allocation: Allocating memory at runtime using new/delete
  • Memory Leak: Allocated memory that is never freed
  • RAII: Resource Acquisition Is Initialization - modern C++ pattern

1. Stack vs Heap Memory: Complete Comparison

Feature Stack Memory Heap Memory
Allocation Method Automatic by compiler Manual using new/malloc
Deallocation Automatic when scope ends Manual using delete/free
Access Speed Very fast (direct CPU instructions) Slower (requires pointer indirection)
Size Limit Small (typically 1-8 MB) Large (limited by OS/available RAM)
Memory Layout Contiguous, LIFO structure Fragmented, random access
Lifetime Function/scope lifetime Until explicitly freed
Flexibility Fixed size at compile time Dynamic size at runtime
Thread Safety Each thread has its own stack Shared across threads (requires synchronization)
Common Uses Local variables, function calls, return addresses Large data, dynamic arrays, objects with varying lifetime
Risk Factors Stack overflow, use-after-return Memory leaks, dangling pointers, fragmentation

Stack vs Heap Examples

1. Stack auto var
int x = 10; // stack
2. Heap with new
int* p = new int(20);
3. Delete single
delete p; p=nullptr;
4. Array on stack
int a[5] = {1,2,3,4,5};
5. Array on heap
int* h = new int[5];
6. delete[] array
delete[] h;
When to Use Stack
  • Small, short-lived variables
  • Known, fixed size at compile time
  • Local variables in functions
  • Temporary calculation results
  • Function parameters and return values
When to Use Heap
  • Large data structures
  • Size unknown at compile time
  • Objects that outlive their creating function
  • Shared data between functions/threads
  • Polymorphic objects (base class pointers)

2. Dynamic Memory Allocation: new and delete

// Dynamic allocation syntax:
type* pointer = new type; // Single object
type* array = new type[size]; // Array of objects

// Deallocation syntax:
delete pointer; // Single object
delete[] array; // Array of objects

// Placement new (advanced):
type* ptr = new(address) type; // Construct at specific address

new / delete Examples

1. new int
int* p = new int;
*p = 7;
2. new int(n)
int* q = new int(42);
3. new Type[n]
double* d = new double[3];
4. delete one
delete q;
5. delete[] many
delete[] d;
6. nothrow new
int* r = new(nothrow) int[1000];
Critical Rules for new/delete:
  • Always match new with delete, new[] with delete[]
  • Never delete memory twice (double-free error)
  • Set pointer to nullptr after deletion
  • Check for allocation failure (use try-catch or std::nothrow)
  • Initialize dynamically allocated memory
  • Implement Rule of Three/Five for classes with dynamic memory

3. Memory Leaks: Detection and Prevention

Memory Leak Examples

1. Leak: no delete
int* p=new int(1);
// forgot delete
2. Fix: pair new/delete
int* p=new int(1);
delete p;
3. Leak: early return
int* p=new int[10];
if (err) return;
4. Fix: RAII vector
vector<int> v(10);
5. Leak: lost pointer
p=new int(2); p=new int(3);
6. Fix: smart pointer
auto sp=make_unique<int>(3);
Prevention Techniques
  • Use smart pointers
  • Implement RAII pattern
  • Follow Rule of Three/Five
  • Prefer stack allocation
  • Use standard containers
Detection Tools
  • Valgrind (Linux/Mac)
  • AddressSanitizer
  • Visual Studio Debugger
  • Manual tracking counters
  • Memory profilers
Common Leak Sources
  • Missing delete statements
  • Early returns/exceptions
  • Circular references
  • Wrong delete (delete vs delete[])
  • Collection of raw pointers

4. Smart Pointers for Memory Management

Smart Pointer Memory Examples

1. unique ownership
auto u = make_unique<Dog>();
2. move unique
auto v = move(u);
3. shared count
auto s1=make_shared<Cat>();
auto s2=s1;
4. weak breaks cycle
weak_ptr<Node> w = n;
5. custom deleter
unique_ptr<FILE,Deleter> f;
6. avoid naked new
auto x=make_shared<int>(5);

Modern C++ Memory Management Philosophy

In modern C++, avoid manual memory management with raw new/delete. Instead, use smart pointers and RAII. Prefer stack allocation for small, short-lived objects. Use unique_ptr for exclusive ownership, shared_ptr only when shared ownership is truly needed, and weak_ptr to observe shared resources without ownership.

5. Practical Applications and Patterns

Dynamic Structure Examples

1. Linked list node
struct Node { int d; Node* next; };
2. Insert at head
n->next=head; head=n;
3. Delete list
while(head){ auto t=head; head=head->next; delete t;}
4. vector growth
vector<int> v; v.push_back(1);
5. resize buffer
v.reserve(100);
6. 2D dynamic
int** g=new int*[n];

6. Best Practices and Performance Optimization

Practice Bad Example Good Example
Memory Allocation int* arr = new int[n]; vector<int> arr(n); or unique_ptr<int[]>
Ownership Transfer Resource* create() { return new Resource(); } unique_ptr<Resource> create() { return make_unique<Resource>(); }
Exception Safety void process() { Resource* r = new Resource(); /* might throw */ delete r; } void process() { auto r = make_unique<Resource>(); /* exception safe */ }
Array Management int** matrix = new int*[rows]; for(i) matrix[i] = new int[cols]; vector<vector<int>> matrix(rows, vector<int>(cols));
Resource Cleanup File* f = fopen(); /* ... */ fclose(f); unique_ptr<FILE, decltype(&fclose)> f(fopen(), &fclose);
Polymorphic Objects Base* obj = new Derived(); delete obj; unique_ptr<Base> obj = make_unique<Derived>();
Memory Management Best Practices
  • Prefer stack allocation for small, short-lived objects
  • Use smart pointers instead of raw new/delete
  • Follow RAII pattern for all resources
  • Implement Rule of Three/Five for resource-owning classes
  • Use standard library containers when possible
  • Always check allocation success
  • Profile before optimizing memory usage
Performance Considerations
  • Heap allocation is 100-1000x slower than stack
  • Memory fragmentation affects long-running programs
  • Cache locality is better with contiguous memory
  • Virtual memory overhead for large allocations
  • Smart pointers have small runtime overhead
  • Custom allocators can improve specific use cases

Memory Optimization Techniques

  • Pool Allocation: Pre-allocate objects of same size
  • Slab Allocation: Allocate in large blocks, manage internally
  • Arena Allocation: Allocate sequentially, free all at once
  • Memory Mapping: Use mmap for very large allocations
  • Custom Allocators: Implement allocators for specific patterns
  • Object Reuse: Object pools for frequently created/destroyed objects

Quick Quiz: Test Your Knowledge

What happens when this code executes?

void process() {
  int* ptr = new int[100];
  if (errorCondition) return;
  delete[] ptr;
}
A) Memory leak if errorCondition is true
B) Always deallocates memory properly
C) Stack overflow
D) Double free error

Summary & Key Takeaways

Stack Memory
  • Automatic allocation/deallocation
  • Very fast (CPU instructions)
  • Limited size (1-8 MB typically)
  • Function/scope lifetime
  • Perfect for local variables
Heap Memory
  • Manual allocation (new/malloc)
  • Manual deallocation (delete/free)
  • Large size (limited by OS/RAM)
  • Programmer-controlled lifetime
  • Flexible but requires management
Smart Pointers
  • unique_ptr: Exclusive ownership
  • shared_ptr: Shared ownership
  • weak_ptr: Non-owning observation
  • Automatic memory management
  • Exception safety guaranteed
Memory Safety
  • RAII pattern for resource management
  • Rule of Three/Five for classes
  • Use tools to detect leaks
  • Avoid manual memory management
  • Prefer standard library containers

Modern C++ Memory Philosophy

In modern C++ (C++11 and later), avoid raw new/delete. Use smart pointers for ownership, stack allocation for local variables, and standard containers for collections. Implement RAII for all resources. Let the compiler and standard library handle memory management whenever possible.

Next Steps

Mastering dynamic memory is crucial for advanced C++ programming. Practice with custom allocators, study memory profiling tools, explore multi-threaded memory management, and learn about memory-mapped files. Understanding memory at a deep level will make you a more effective systems programmer.

Frequently asked questions

What is a memory leak?

Allocated heap memory never freed—program consumes more RAM over time.

When should I use shared_ptr vs unique_ptr?

unique_ptr for exclusive ownership; shared_ptr when multiple owners must share lifetime.

Is malloc the same as new?

Both allocate heap memory; new calls constructors, malloc does not—prefer new/smart pointers in C++.