Course contentsShow
← Rust
Lesson 388 of 1,9104. Lifetimes and Advanced OwnershipFree lesson

Cyclic Reference Management

Use reference counting with weak pointers to resolve cyclic memory dependencies.

In this lesson, you will learn how to break memory leaks caused by circular dependencies using Weak pointers in Rust's reference counting system.

The Problem: Memory Cycles

When you use Rc (Reference Counted) smart pointers, Rust keeps track of how many owners a piece of data has. As long as the count is above zero, the data stays in memory. However, if you create a "cycle"—where Object A points to Object B, and Object B points back to Object A—the reference counts of both objects will never reach zero, even if your program is finished with them. This creates a memory leak.

The Solution: Weak Pointers

To break these cycles, Rust provides std::rc::Weak. A Weak pointer allows you to reference an Rc allocation without increasing its "strong" reference count. Because a Weak pointer doesn't contribute to ownership, it doesn't keep the data alive.

When you need to access the data held by a Weak pointer, you must call .upgrade(). This returns an Option<Rc<T>>. If the original Rc has already been dropped, upgrade() returns None, safely preventing you from accessing dangling memory.

Code Example

Imagine two nodes in a graph where one needs to point back to its parent:

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

struct Node {
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>,
}

fn main() {
    let parent = Rc::new(Node { 
        parent: RefCell::new(Weak::new()), 
        children: RefCell::new(Vec::new()) 
    });
    
    let child = Rc::new(Node { 
        parent: RefCell::new(Rc::downgrade(&parent)), 
        children: RefCell::new(Vec::new()) 
    });
    
    parent.children.borrow_mut().push(child);
}

In this snippet, parent owns child via a standard Rc, but child holds a Weak pointer to parent. Because the Weak reference doesn't count toward the parent’s ownership, the reference count for parent remains correct, and the cycle is broken. When the owner of parent drops the Rc, the memory is cleaned up correctly, and the Weak pointer in child simply becomes invalid.

Key Takeaway: Use Rc for owning relationships and Weak for back-references or non-owning links to prevent memory leaks in cyclic data structures.