Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Rust protects against many memory issues thanks to its safety rules. However it cannot protect against everything. For instance, the Rc pointer is powerful to share an object through different parts of the code, but when used with the RefCell pointer it may create reference cycles. Reference cycles, once created, cannot be removed from memory. When their variables go out of scope, they stay in memory: they generate memory leaks.

37.3.1Strong cycle

Cycles are not bad by nature, but they must not be made of only strong references. Instead they must contain some Weak references.

To begin with, let us show how to create a reference cycle with strong references only. First we import the pointer types:

We create a List<T> structure that contains a value field and a next field for chaining the next element:

We use a RefCell to be able to modify the next field even inside an immutable List<T> object. Inside the RefCell we have an Option value that we use as following:

We implement a next() function that returns a Some with a new reference to the next element or None for the end of the list:

We create a list a with just one element in it:

Couldn't automatically determine type of variable `a`.
Please give it an explicit type.

We create a list b with one element, and set the next to be a:

We then modify the next field of the single element of a to point to b using a new Rc reference on it:

We have now our cycle, as shown in the following diagram:

    ┌────┐
a---->│ -5 │
    └────┘
     |  ^
     |  |
     |  |
     v  |
    ┌────┐
b---->│ 13 │
    └────┘

We use another pointer to iterate through the list values:

We print some of the first values of this infinite list:

37.3.2Weak references

Cycles may be useful, like for instance inside graph structures. However they must be dropable when the variables go out of scope. To make this possible we need to use at least one Weak reference inside each cycle.

37.3.2.1Proof that the cycle is alive

We come back to our strong reference cycle problem from above. We will see how a weak reference helps us see that the cycle is still in memory. To create a weak reference we use the downgrade() method of Rc. It increments the counter of weak references and returns a Weak object. Here we create a weak reference on a:

We then drop a and b:

On the Weak object we can call the method upgrade() that returns an Option. If the object pointed to has been destroyed, None is returned. Otherwise Some is returned with a strong reference Rc to it.

37.3.3Droppable cycle

Using one Weak reference inside our cycle will make it droppable. To show this we need to build a special enum type that can have either a strong reference or a weak reference.

We start by importing the reference types we need:

Then we create our generic enum that will be able to contain either a termination (Nil), a weak reference or a strong reference:

We define our generic structure List<T> using the Next<T> enum:

The next() method has a third case in its match now:

To define our cycle, we start with the a list:

Then we define b with a weak reference on a:

Finally we change the termination of a into a strong reference on b:

Here is our cycle, with one weak link (b on a) and one strong link (a on b):

    ┌────┐
a---->│ -5 │
    └────┘
     ¦  ^
     ¦  |
     ¦  |
     v  |
    ┌────┐
b---->│ 13 │
    └────┘

We can see the cycle is correct by printing its first elements using the next() method:

Let us now define a weak reference on a:

And try to drop a and b:

If we check the weak reference c, we see that a does not exist anymore. The cycle has been dropped correctly: