Course contentsShow
← Rust
Lesson 1001 of 1,9109. Smart Pointers and Interior MutabilityFree lesson

Weak References and Circular Dependencies

Break cycles in graph structures using weak pointers to prevent memory leaks.

In this lesson, you will learn how to prevent memory leaks in graph-like structures by using Weak pointers to break circular dependencies.

The Problem: Reference Cycles

When you use Rc<T>, Rust keeps an item in memory as long as there is at least one active reference to it. This works perfectly for tree structures, but it fails in graphs where nodes can point to each other.

Imagine two nodes, A and B. If A holds an Rc pointing to B, and B holds an Rc pointing to A, their reference counts will never drop to zero. Even if your program loses access to both nodes, the memory remains allocated because they are still "holding" each other. This is a memory leak.

The Solution: Weak<T>

To solve this, we introduce Weak<T>. A Weak reference does not express ownership and does not increment the "strong" reference count that keeps the data alive.

When you define a structure that needs to point backward (like a parent pointer in a tree or a bi-directional edge in a graph), you use Rc<T> for the primary child references and Weak<T> for the back-references.

use std::rc::{Rc, Weak};

struct Node {
    value: i32,
    parent: Option<Weak<Node>>,
}

// Creating a cycle-free reference
let leaf = Rc::new(Node { value: 5, parent: None });
let root = Rc::new(Node { value: 10, parent: Some(Rc::downgrade(&leaf)) });

Accessing Data

Because a Weak pointer doesn't guarantee the data still exists, you cannot access the value directly. You must use the upgrade() method, which returns an Option<Rc<T>>. If the original Rc has been dropped, upgrade() returns None, allowing you to handle the case where the data is already gone safely.

By using Weak pointers for non-owning references (like back-pointers or caches), you ensure that the reference count can eventually reach zero, allowing Rust to deallocate the memory and reclaim your system resources.

Key Takeaway: Use Rc<T> for owning relationships and Weak<T> for back-references or non-owning links to break circular dependencies and prevent permanent memory leaks.