Course contentsShow
← Rust
Lesson 245 of 1,9103. Borrowing and ReferencesFree lesson

Cyclic References with Weak Pointers

Break reference cycles by using weak references to prevent memory leaks.

In this lesson, you will learn how to prevent memory leaks in Rust by using Weak pointers to break circular dependencies between data structures.

The Problem: When References Go in Circles

When we use Rc<T> (Reference Counted pointers) to share ownership, Rust keeps track of how many pointers point to a value. The value is only cleaned up from memory when that count hits zero.

A "cyclic reference" occurs when two objects hold Rc pointers to each other. For example, if a parent owns a child, and the child also holds an Rc pointer back to the parent, both reference counts will stay at 1 forever. Even if your program stops using these objects, they will never be dropped because they are keeping each other "alive." This is a memory leak.

The Solution: Weak Pointers

To break this cycle, we use a Weak<T> pointer. Unlike Rc<T>, a Weak pointer does not express ownership. It doesn't contribute to the reference count that keeps the data alive.

Think of it as a "reference that might disappear." Because it doesn't own the data, you cannot access the value directly. You must first call .upgrade(), which returns an Option<Rc<T>>. If the original data still exists, you get an Rc back to use; if the data has already been dropped, you get None.

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

struct Node {
    // We use Weak here to avoid a cycle
    parent: RefCell<Weak<Node>>,
}

fn main() {
    let parent = Rc::new(Node { parent: RefCell::new(Weak::new()) });
    let child = Rc::new(Node { parent: RefCell::new(Rc::downgrade(&parent)) });
    
    // Now the child points to the parent, but does NOT own it.
    // Memory will be cleaned up properly when the parent goes out of scope.
}

By using Weak pointers for "back-references," you allow your data structures to point to each other without creating an unbreakable loop of ownership, ensuring that Rust’s memory management can successfully reclaim your data.

Key Takeaway: Use Weak pointers for back-references in cyclic data structures to prevent memory leaks by allowing reference counts to return to zero.