Skip to content

How to Fix C++ Shared Pointer Cycle Memory Leaks

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about How to Fix C++ Shared Pointer Cycle Memory Leaks. We cover key concepts, practical examples, and best practices.

C++ std::shared_ptr cycles occur when two objects hold shared_ptr references to each other, preventing either from being destroyed. This causes memory leaks even though smart pointers are used everywhere.

Quick Fix

Wrong

struct Node {
    std::shared_ptr<Node> next;
};

int main() {
    auto a = std::make_shared<Node>();
    auto b = std::make_shared<Node>();
    a->next = b;
    b->next = a;  // cycle!
}

Both a and b have a reference count of 2. When main exits, each drops to 1, and neither is destroyed.

struct Node {
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> parent;  // use weak_ptr to break cycle
};

int main() {
    auto root = std::make_shared<Node>();
    auto child = std::make_shared<Node>();
    root->next = child;
    child->parent = root;  // weak_ptr does not increase ref count
}

When root goes out of scope, child's reference count drops to 0 and both are destroyed.

Fix for observer pattern

struct Observer {
    std::weak_ptr<Subject> subject;
};

struct Subject {
    std::vector<std::shared_ptr<Observer>> observers;
};

Fix for caching

struct Cache {
    std::map<int, std::weak_ptr<ExpensiveObject>> cache;
};

auto getObject(int id) -> std::shared_ptr<ExpensiveObject> {
    if (auto it = cache.find(id); it != cache.end()) {
        if (auto obj = it->second.lock()) return obj;
        cache.erase(it);
    }
    auto obj = std::make_shared<ExpensiveObject>(id);
    cache[id] = obj;
    return obj;
}

Prevention

  • Use weak_ptr for back-references in tree or graph structures.
  • Use unique_ptr for exclusive ownership (trees, lists).
  • Avoid bare new and delete entirely.
  • Use std::make_shared instead of std::shared_ptr(new T).
  • Profile memory usage to detect leaks from reference cycles.

DodaTech Tools

Doda Browser's C++ memory profiler detects shared_ptr cycles through reference graph analysis. DodaZIP archives heap profiles for leak detection. Durga Antivirus Pro scans for memory leaks in long-running processes.

Common Mistakes with smart pointer cycle

  1. Using foldl instead of foldl' causing stack overflow on large lists
  2. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  3. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable

These mistakes appear frequently in real-world CPP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

How do I detect shared_ptr cycles in a running program?

Use Valgrind's massif or heaptrack to profile memory. Reference cycles show as persistent allocations. Chrome's DevTools-style memory profilers can visualize reference graphs.

Can `unique_ptr` have cycles?

No, unique_ptr enforces exclusive ownership and cannot be copied, preventing cycles by design. Prefer unique_ptr unless shared ownership is truly required.

When should I use `shared_ptr` vs `weak_ptr`?

Use shared_ptr for ownership. Use weak_ptr for temporary access that should not prevent object destruction. Always use weak_ptr::lock() to get a shared_ptr before accessing the object.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro