Course contentsShow
← Rust
Lesson 39 of 1,9101. Rust Fundamentals and ToolingFree lesson

Weak References and Cycle Breaking

Prevent memory leaks in complex structures by using weak references with reference-counted pointers.

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

The Problem: Reference Cycles

You have already learned about Rc<T>, which allows multiple owners for a single piece of data on the heap. An Rc<T> keeps track of how many references exist; it only cleans up the data when that count reaches zero.

However, a dangerous situation occurs if you create a reference cycle. Imagine two objects, A and B, that both contain an Rc pointing to the other. Even if your main program drops its references to both A and B, the count for each object will never reach zero because they are still pointing at each other. They become "zombies"—memory that can never be freed because the program no longer has a way to reach them.

The Solution: Weak References

To break this cycle, we use std::rc::Weak. A Weak reference is a special pointer that does not contribute to the ownership count. It says: "I want to look at this data if it exists, but I don't demand that it stays alive."

Think of Rc as an "owner" and Weak as an "observer."

A Simple Illustration

If you have a Node structure, you might hold a child using Rc (to own it) but hold a reference to a parent using Weak. Because the parent doesn't "own" the child via a strong reference, the cycle is broken:

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

struct Node {
    value: i32,
    parent: RefCell<Weak<Node>>, // Weak reference to break the cycle
    children: RefCell<Vec<Rc<Node>>>,
}

When you want to use a Weak reference, you call .upgrade(). This attempts to turn the Weak pointer into an Rc. If the original data has already been dropped and cleaned up, .upgrade() returns None. If it still exists, you get an Rc back, and you can safely access the data.

This pattern allows your data structures to maintain complex relationships—like trees or graphs—without leaking memory, because the "backwards" links don't prevent the cleanup of the structure.

Key Takeaway: Use Weak references when you need to create links between objects without creating a cycle of ownership that prevents memory from being freed.