C++ shared_ptr Cycles: Parent/Child, Observer, Graph, Cache Patterns [#33-4]
이 글의 핵심
Recognize shared_ptr cycles in trees, observers, graphs, and caches—then break them with weak_ptr and clear ownership.
Introduction: why shared_ptr cycles keep happening
Scenarios
- Chat Room ↔ Session zombies.
- DOM trees with parent/child shared_ptr edges.
- Event bus retaining
shared_ptr<Observer>. - Graph nodes with
shared_ptrneighbors.
Essence: refcount never reaches 0 in a cycle—weak_ptr on the non-owning direction breaks it.
Topics: four patterns (parent/child, observer, graph, cache), complete examples, mistakes, best practices, diagnostics, performance.
Pattern 1: Parent/child tree
Wrong: shared_ptr parent in child and shared_ptr children in parent ⇒ cycle.
Right: vector<shared_ptr<Child>> + weak_ptr<Parent> (or the reverse, but one direction owns).
enable_shared_from_this to set weak_ptr parent when adding children.
Pattern 2: Observer
Subject should store weak_ptr<Observer>, not shared_ptr, unless it truly co-owns observers.
Pattern 3: Graph
Either weak_ptr back-edges, unique_ptr ownership with node indices, or central Graph owning storage.
Pattern 4: Cache
weak_ptr values let entries die when external **shared_ptr**s disappear; lock() misses reload assets.
Diagnostics
Leaks without obvious ASan? Draw ownership graph. Tools: heap profiling, Valgrind (cycle behavior differs), reasoning about strong counts.
Performance
weak_ptr storage is cheap; lock() costs like shared_ptr copy when upgrading.
Full runnable listings (tree, observer, graph snippets) follow the same structure as the main series posts.
Keywords
shared_ptr cycle, weak_ptr, observer, cache, memory leak