Where an object lives decides how long it lives. C++ has four storage durations; knowing them is the key to avoiding dangling pointers.
Memory segments of a process
| Region | Holds | Lifetime | Managed by |
|---|---|---|---|
| Stack | Local variables, parameters, return addresses | Until the enclosing block ends | Automatic (push/pop) |
| Heap (free store) | Objects from new / containers' buffers | Until delete | You (or RAII owners) |
| Static / global data | Globals, static locals & members | Whole program | Runtime |
| Code (text) | Machine instructions, string literals (read-only data) | Whole program | Loader |
Storage durations
#include <iostream>
#include <memory>
#include <string>
struct Tracer {
std::string name;
explicit Tracer(std::string n) : name(std::move(n)) { std::cout << "+ " << name << '\n'; }
~Tracer() { std::cout << "- " << name << '\n'; }
};
Tracer global("static"); // static: before main, destroyed after main
void f() {
static Tracer once("static-local"); // created on first call only
Tracer local("automatic"); // destroyed at the end of f
}
int main() {
std::cout << "main starts\n";
f();
f();
auto heap = std::make_unique<Tracer>("dynamic"); // lives until its owner lets go
heap.reset();
std::cout << "main ends\n";
}+ static
main starts
+ static-local
+ automatic
- automatic
+ automatic
- automatic
+ dynamic
- dynamic
main ends
- static-local
- staticAutomatic — block-scoped locals. Destroyed in reverse order of construction when the block ends.
Static — globals, namespace variables,
staticlocals/members. Static locals are initialised on first use (thread-safe since C++11).Dynamic —
new/delete, or owned by smart pointers/containers.Thread —
thread_localvariables: one instance per thread.
Stack vs heap
| Stack | Heap | |
|---|---|---|
| Allocation speed | Very fast (move a pointer) | Slower (allocator bookkeeping) |
| Size limit | Small (~1–8 MB) | Large (up to available memory) |
| Lifetime | Tied to scope | Explicit / owner-controlled |
| Fragmentation | None | Possible |
| Typical failure | Stack overflow (deep recursion, huge local arrays) | Leaks, use-after-free |
Object size & alignment
#include <iostream>
struct Padded { char a; int b; char c; }; // 1 + 3 pad + 4 + 1 + 3 pad
struct Ordered { int b; char a; char c; }; // 4 + 1 + 1 + 2 pad
struct Empty {};
int main() {
std::cout << sizeof(Padded) << ' ' << sizeof(Ordered) << ' ' << alignof(int) << ' ' << sizeof(Empty) << '\n';
}12 8 4 1Why is the stack faster than the heap?
In what order are local objects destroyed?