Files
docs-rust/ch15/ch15-06-reference-cycles.html
2026-06-22 21:27:36 +05:30

467 lines
28 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Reference Cycles Can Leak Memory</title>
</head>
<body>
<h2 id="reference-cycles-can-leak-memory"><a class="header" href="#reference-cycles-can-leak-memory">Reference Cycles Can Leak Memory</a></h2>
<p>Rusts memory safety guarantees make it difficult, but not impossible, to
accidentally create memory that is never cleaned up (known as a <em>memory leak</em>).
Preventing memory leaks entirely is not one of Rusts guarantees, meaning
memory leaks are memory safe in Rust. We can see that Rust allows memory leaks
by using <code>Rc&lt;T&gt;</code> and <code>RefCell&lt;T&gt;</code>: Its possible to create references where
items refer to each other in a cycle. This creates memory leaks because the
reference count of each item in the cycle will never reach 0, and the values
will never be dropped.</p>
<h3 id="creating-a-reference-cycle"><a class="header" href="#creating-a-reference-cycle">Creating a Reference Cycle</a></h3>
<p>Lets look at how a reference cycle might happen and how to prevent it,
starting with the definition of the <code>List</code> enum and a <code>tail</code> method in Listing
15-25.</p>
<figure class="listing" id="listing-15-25">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug)]
enum List {
Cons(i32, RefCell&lt;Rc&lt;List&gt;&gt;),
Nil,
}
impl List {
fn tail(&amp;self) -&gt; Option&lt;&amp;RefCell&lt;Rc&lt;List&gt;&gt;&gt; {
match self {
Cons(_, item) =&gt; Some(item),
Nil =&gt; None,
}
}
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-15-25">Listing 15-25</a>: A cons list definition that holds a <code>RefCell&lt;T&gt;</code> so that we can modify what a <code>Cons</code> variant is referring to</figcaption>
</figure>
<p>Were using another variation of the <code>List</code> definition from Listing 15-5. The
second element in the <code>Cons</code> variant is now <code>RefCell&lt;Rc&lt;List&gt;&gt;</code>, meaning that
instead of having the ability to modify the <code>i32</code> value as we did in Listing
15-24, we want to modify the <code>List</code> value a <code>Cons</code> variant is pointing to.
Were also adding a <code>tail</code> method to make it convenient for us to access the
second item if we have a <code>Cons</code> variant.</p>
<p>In Listing 15-26, were adding a <code>main</code> function that uses the definitions in
Listing 15-25. This code creates a list in <code>a</code> and a list in <code>b</code> that points to
the list in <code>a</code>. Then, it modifies the list in <code>a</code> to point to <code>b</code>, creating a
reference cycle. There are <code>println!</code> statements along the way to show what the
reference counts are at various points in this process.</p>
<figure class="listing" id="listing-15-26">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">use crate::List::{Cons, Nil};
</span><span class="boring">use std::cell::RefCell;
</span><span class="boring">use std::rc::Rc;
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">enum List {
</span><span class="boring"> Cons(i32, RefCell&lt;Rc&lt;List&gt;&gt;),
</span><span class="boring"> Nil,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl List {
</span><span class="boring"> fn tail(&amp;self) -&gt; Option&lt;&amp;RefCell&lt;Rc&lt;List&gt;&gt;&gt; {
</span><span class="boring"> match self {
</span><span class="boring"> Cons(_, item) =&gt; Some(item),
</span><span class="boring"> Nil =&gt; None,
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
println!("a initial rc count = {}", Rc::strong_count(&amp;a));
println!("a next item = {:?}", a.tail());
let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&amp;a))));
println!("a rc count after b creation = {}", Rc::strong_count(&amp;a));
println!("b initial rc count = {}", Rc::strong_count(&amp;b));
println!("b next item = {:?}", b.tail());
if let Some(link) = a.tail() {
*link.borrow_mut() = Rc::clone(&amp;b);
}
println!("b rc count after changing a = {}", Rc::strong_count(&amp;b));
println!("a rc count after changing a = {}", Rc::strong_count(&amp;a));
// Uncomment the next line to see that we have a cycle;
// it will overflow the stack.
// println!("a next item = {:?}", a.tail());
}</code></pre>
<figcaption><a href="#listing-15-26">Listing 15-26</a>: Creating a reference cycle of two <code>List</code> values pointing to each other</figcaption>
</figure>
<p>We create an <code>Rc&lt;List&gt;</code> instance holding a <code>List</code> value in the variable <code>a</code>
with an initial list of <code>5, Nil</code>. We then create an <code>Rc&lt;List&gt;</code> instance holding
another <code>List</code> value in the variable <code>b</code> that contains the value <code>10</code> and
points to the list in <code>a</code>.</p>
<p>We modify <code>a</code> so that it points to <code>b</code> instead of <code>Nil</code>, creating a cycle. We
do that by using the <code>tail</code> method to get a reference to the
<code>RefCell&lt;Rc&lt;List&gt;&gt;</code> in <code>a</code>, which we put in the variable <code>link</code>. Then, we use
the <code>borrow_mut</code> method on the <code>RefCell&lt;Rc&lt;List&gt;&gt;</code> to change the value inside
from an <code>Rc&lt;List&gt;</code> that holds a <code>Nil</code> value to the <code>Rc&lt;List&gt;</code> in <code>b</code>.</p>
<p>When we run this code, keeping the last <code>println!</code> commented out for the
moment, well get this output:</p>
<pre><code class="language-console">$ cargo run
Compiling cons-list v0.1.0 (file:///projects/cons-list)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.53s
Running `target/debug/cons-list`
a initial rc count = 1
a next item = Some(RefCell { value: Nil })
a rc count after b creation = 2
b initial rc count = 1
b next item = Some(RefCell { value: Cons(5, RefCell { value: Nil }) })
b rc count after changing a = 2
a rc count after changing a = 2
</code></pre>
<p>The reference count of the <code>Rc&lt;List&gt;</code> instances in both <code>a</code> and <code>b</code> is 2 after
we change the list in <code>a</code> to point to <code>b</code>. At the end of <code>main</code>, Rust drops the
variable <code>b</code>, which decreases the reference count of the <code>b</code> <code>Rc&lt;List&gt;</code>
instance from 2 to 1. The memory that <code>Rc&lt;List&gt;</code> has on the heap wont be
dropped at this point because its reference count is 1, not 0. Then, Rust drops
<code>a</code>, which decreases the reference count of the <code>a</code> <code>Rc&lt;List&gt;</code> instance from 2
to 1 as well. This instances memory cant be dropped either, because the other
<code>Rc&lt;List&gt;</code> instance still refers to it. The memory allocated to the list will
remain uncollected forever. To visualize this reference cycle, weve created
the diagram in Figure 15-4.</p>
<img alt="A rectangle labeled &#39;a&#39; that points to a rectangle containing the integer 5. A rectangle labeled &#39;b&#39; that points to a rectangle containing the integer 10. The rectangle containing 5 points to the rectangle containing 10, and the rectangle containing 10 points back to the rectangle containing 5, creating a cycle." src="../img/trpl15-04.svg" class="center" />
<p><span class="caption">Figure 15-4: A reference cycle of lists <code>a</code> and <code>b</code>
pointing to each other</span></p>
<p>If you uncomment the last <code>println!</code> and run the program, Rust will try to
print this cycle with <code>a</code> pointing to <code>b</code> pointing to <code>a</code> and so forth until it
overflows the stack.</p>
<p>Compared to a real-world program, the consequences of creating a reference
cycle in this example arent very dire: Right after we create the reference
cycle, the program ends. However, if a more complex program allocated lots of
memory in a cycle and held onto it for a long time, the program would use more
memory than it needed and might overwhelm the system, causing it to run out of
available memory.</p>
<p>Creating reference cycles is not easily done, but its not impossible either.
If you have <code>RefCell&lt;T&gt;</code> values that contain <code>Rc&lt;T&gt;</code> values or similar nested
combinations of types with interior mutability and reference counting, you must
ensure that you dont create cycles; you cant rely on Rust to catch them.
Creating a reference cycle would be a logic bug in your program that you should
use automated tests, code reviews, and other software development practices to
minimize.</p>
<p>Another solution for avoiding reference cycles is reorganizing your data
structures so that some references express ownership and some references dont.
As a result, you can have cycles made up of some ownership relationships and
some non-ownership relationships, and only the ownership relationships affect
whether or not a value can be dropped. In Listing 15-25, we always want <code>Cons</code>
variants to own their list, so reorganizing the data structure isnt possible.
Lets look at an example using graphs made up of parent nodes and child nodes
to see when non-ownership relationships are an appropriate way to prevent
reference cycles.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="preventing-reference-cycles-turning-an-rct-into-a-weakt"></a></p>
<h3 id="preventing-reference-cycles-using-weakt"><a class="header" href="#preventing-reference-cycles-using-weakt">Preventing Reference Cycles Using <code>Weak&lt;T&gt;</code></a></h3>
<p>So far, weve demonstrated that calling <code>Rc::clone</code> increases the
<code>strong_count</code> of an <code>Rc&lt;T&gt;</code> instance, and an <code>Rc&lt;T&gt;</code> instance is only cleaned
up if its <code>strong_count</code> is 0. You can also create a weak reference to the
value within an <code>Rc&lt;T&gt;</code> instance by calling <code>Rc::downgrade</code> and passing a
reference to the <code>Rc&lt;T&gt;</code>. <em>Strong references</em> are how you can share ownership
of an <code>Rc&lt;T&gt;</code> instance. <em>Weak references</em> dont express an ownership
relationship, and their count doesnt affect when an <code>Rc&lt;T&gt;</code> instance is
cleaned up. They wont cause a reference cycle, because any cycle involving
some weak references will be broken once the strong reference count of values
involved is 0.</p>
<p>When you call <code>Rc::downgrade</code>, you get a smart pointer of type <code>Weak&lt;T&gt;</code>.
Instead of increasing the <code>strong_count</code> in the <code>Rc&lt;T&gt;</code> instance by 1, calling
<code>Rc::downgrade</code> increases the <code>weak_count</code> by 1. The <code>Rc&lt;T&gt;</code> type uses
<code>weak_count</code> to keep track of how many <code>Weak&lt;T&gt;</code> references exist, similar to
<code>strong_count</code>. The difference is the <code>weak_count</code> doesnt need to be 0 for the
<code>Rc&lt;T&gt;</code> instance to be cleaned up.</p>
<p>Because the value that <code>Weak&lt;T&gt;</code> references might have been dropped, to do
anything with the value that a <code>Weak&lt;T&gt;</code> is pointing to you must make sure the
value still exists. Do this by calling the <code>upgrade</code> method on a <code>Weak&lt;T&gt;</code>
instance, which will return an <code>Option&lt;Rc&lt;T&gt;&gt;</code>. Youll get a result of <code>Some</code>
if the <code>Rc&lt;T&gt;</code> value has not been dropped yet and a result of <code>None</code> if the
<code>Rc&lt;T&gt;</code> value has been dropped. Because <code>upgrade</code> returns an <code>Option&lt;Rc&lt;T&gt;&gt;</code>,
Rust will ensure that the <code>Some</code> case and the <code>None</code> case are handled, and
there wont be an invalid pointer.</p>
<p>As an example, rather than using a list whose items know only about the next
item, well create a tree whose items know about their child items <em>and</em> their
parent items.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="creating-a-tree-data-structure-a-node-with-child-nodes"></a></p>
<h4 id="creating-a-tree-data-structure"><a class="header" href="#creating-a-tree-data-structure">Creating a Tree Data Structure</a></h4>
<p>To start, well build a tree with nodes that know about their child nodes.
Well create a struct named <code>Node</code> that holds its own <code>i32</code> value as well as
references to its child <code>Node</code> values:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre class="playground"><code class="language-rust edition2024">use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug)]
struct Node {
value: i32,
children: RefCell&lt;Vec&lt;Rc&lt;Node&gt;&gt;&gt;,
}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> let leaf = Rc::new(Node {
</span><span class="boring"> value: 3,
</span><span class="boring"> children: RefCell::new(vec![]),
</span><span class="boring"> });
</span><span class="boring">
</span><span class="boring"> let branch = Rc::new(Node {
</span><span class="boring"> value: 5,
</span><span class="boring"> children: RefCell::new(vec![Rc::clone(&amp;leaf)]),
</span><span class="boring"> });
</span><span class="boring">}</span></code></pre>
<p>We want a <code>Node</code> to own its children, and we want to share that ownership with
variables so that we can access each <code>Node</code> in the tree directly. To do this,
we define the <code>Vec&lt;T&gt;</code> items to be values of type <code>Rc&lt;Node&gt;</code>. We also want to
modify which nodes are children of another node, so we have a <code>RefCell&lt;T&gt;</code> in
<code>children</code> around the <code>Vec&lt;Rc&lt;Node&gt;&gt;</code>.</p>
<p>Next, well use our struct definition and create one <code>Node</code> instance named
<code>leaf</code> with the value <code>3</code> and no children, and another instance named <code>branch</code>
with the value <code>5</code> and <code>leaf</code> as one of its children, as shown in Listing 15-27.</p>
<figure class="listing" id="listing-15-27">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">use std::cell::RefCell;
</span><span class="boring">use std::rc::Rc;
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Node {
</span><span class="boring"> value: i32,
</span><span class="boring"> children: RefCell&lt;Vec&lt;Rc&lt;Node&gt;&gt;&gt;,
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let leaf = Rc::new(Node {
value: 3,
children: RefCell::new(vec![]),
});
let branch = Rc::new(Node {
value: 5,
children: RefCell::new(vec![Rc::clone(&amp;leaf)]),
});
}</code></pre>
<figcaption><a href="#listing-15-27">Listing 15-27</a>: Creating a <code>leaf</code> node with no children and a <code>branch</code> node with <code>leaf</code> as one of its children</figcaption>
</figure>
<p>We clone the <code>Rc&lt;Node&gt;</code> in <code>leaf</code> and store that in <code>branch</code>, meaning the
<code>Node</code> in <code>leaf</code> now has two owners: <code>leaf</code> and <code>branch</code>. We can get from
<code>branch</code> to <code>leaf</code> through <code>branch.children</code>, but theres no way to get from
<code>leaf</code> to <code>branch</code>. The reason is that <code>leaf</code> has no reference to <code>branch</code> and
doesnt know theyre related. We want <code>leaf</code> to know that <code>branch</code> is its
parent. Well do that next.</p>
<h4 id="adding-a-reference-from-a-child-to-its-parent"><a class="header" href="#adding-a-reference-from-a-child-to-its-parent">Adding a Reference from a Child to Its Parent</a></h4>
<p>To make the child node aware of its parent, we need to add a <code>parent</code> field to
our <code>Node</code> struct definition. The trouble is in deciding what the type of
<code>parent</code> should be. We know it cant contain an <code>Rc&lt;T&gt;</code>, because that would
create a reference cycle with <code>leaf.parent</code> pointing to <code>branch</code> and
<code>branch.children</code> pointing to <code>leaf</code>, which would cause their <code>strong_count</code>
values to never be 0.</p>
<p>Thinking about the relationships another way, a parent node should own its
children: If a parent node is dropped, its child nodes should be dropped as
well. However, a child should not own its parent: If we drop a child node, the
parent should still exist. This is a case for weak references!</p>
<p>So, instead of <code>Rc&lt;T&gt;</code>, well make the type of <code>parent</code> use <code>Weak&lt;T&gt;</code>,
specifically a <code>RefCell&lt;Weak&lt;Node&gt;&gt;</code>. Now our <code>Node</code> struct definition looks
like this:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre class="playground"><code class="language-rust edition2024">use std::cell::RefCell;
use std::rc::{Rc, Weak};
#[derive(Debug)]
struct Node {
value: i32,
parent: RefCell&lt;Weak&lt;Node&gt;&gt;,
children: RefCell&lt;Vec&lt;Rc&lt;Node&gt;&gt;&gt;,
}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> let leaf = Rc::new(Node {
</span><span class="boring"> value: 3,
</span><span class="boring"> parent: RefCell::new(Weak::new()),
</span><span class="boring"> children: RefCell::new(vec![]),
</span><span class="boring"> });
</span><span class="boring">
</span><span class="boring"> println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
</span><span class="boring">
</span><span class="boring"> let branch = Rc::new(Node {
</span><span class="boring"> value: 5,
</span><span class="boring"> parent: RefCell::new(Weak::new()),
</span><span class="boring"> children: RefCell::new(vec![Rc::clone(&amp;leaf)]),
</span><span class="boring"> });
</span><span class="boring">
</span><span class="boring"> *leaf.parent.borrow_mut() = Rc::downgrade(&amp;branch);
</span><span class="boring">
</span><span class="boring"> println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
</span><span class="boring">}</span></code></pre>
<p>A node will be able to refer to its parent node but doesnt own its parent. In
Listing 15-28, we update <code>main</code> to use this new definition so that the <code>leaf</code>
node will have a way to refer to its parent, <code>branch</code>.</p>
<figure class="listing" id="listing-15-28">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">use std::cell::RefCell;
</span><span class="boring">use std::rc::{Rc, Weak};
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Node {
</span><span class="boring"> value: i32,
</span><span class="boring"> parent: RefCell&lt;Weak&lt;Node&gt;&gt;,
</span><span class="boring"> children: RefCell&lt;Vec&lt;Rc&lt;Node&gt;&gt;&gt;,
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let leaf = Rc::new(Node {
value: 3,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![]),
});
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
let branch = Rc::new(Node {
value: 5,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![Rc::clone(&amp;leaf)]),
});
*leaf.parent.borrow_mut() = Rc::downgrade(&amp;branch);
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
}</code></pre>
<figcaption><a href="#listing-15-28">Listing 15-28</a>: A <code>leaf</code> node with a weak reference to its parent node, <code>branch</code></figcaption>
</figure>
<p>Creating the <code>leaf</code> node looks similar to Listing 15-27 with the exception of
the <code>parent</code> field: <code>leaf</code> starts out without a parent, so we create a new,
empty <code>Weak&lt;Node&gt;</code> reference instance.</p>
<p>At this point, when we try to get a reference to the parent of <code>leaf</code> by using
the <code>upgrade</code> method, we get a <code>None</code> value. We see this in the output from the
first <code>println!</code> statement:</p>
<pre><code class="language-text">leaf parent = None
</code></pre>
<p>When we create the <code>branch</code> node, it will also have a new <code>Weak&lt;Node&gt;</code>
reference in the <code>parent</code> field because <code>branch</code> doesnt have a parent node. We
still have <code>leaf</code> as one of the children of <code>branch</code>. Once we have the <code>Node</code>
instance in <code>branch</code>, we can modify <code>leaf</code> to give it a <code>Weak&lt;Node&gt;</code> reference
to its parent. We use the <code>borrow_mut</code> method on the <code>RefCell&lt;Weak&lt;Node&gt;&gt;</code> in
the <code>parent</code> field of <code>leaf</code>, and then we use the <code>Rc::downgrade</code> function to
create a <code>Weak&lt;Node&gt;</code> reference to <code>branch</code> from the <code>Rc&lt;Node&gt;</code> in <code>branch</code>.</p>
<p>When we print the parent of <code>leaf</code> again, this time well get a <code>Some</code> variant
holding <code>branch</code>: Now <code>leaf</code> can access its parent! When we print <code>leaf</code>, we
also avoid the cycle that eventually ended in a stack overflow like we had in
Listing 15-26; the <code>Weak&lt;Node&gt;</code> references are printed as <code>(Weak)</code>:</p>
<pre><code class="language-text">leaf parent = Some(Node { value: 5, parent: RefCell { value: (Weak) },
children: RefCell { value: [Node { value: 3, parent: RefCell { value: (Weak) },
children: RefCell { value: [] } }] } })
</code></pre>
<p>The lack of infinite output indicates that this code didnt create a reference
cycle. We can also tell this by looking at the values we get from calling
<code>Rc::strong_count</code> and <code>Rc::weak_count</code>.</p>
<h4 id="visualizing-changes-to-strong_count-and-weak_count"><a class="header" href="#visualizing-changes-to-strong_count-and-weak_count">Visualizing Changes to <code>strong_count</code> and <code>weak_count</code></a></h4>
<p>Lets look at how the <code>strong_count</code> and <code>weak_count</code> values of the <code>Rc&lt;Node&gt;</code>
instances change by creating a new inner scope and moving the creation of
<code>branch</code> into that scope. By doing so, we can see what happens when <code>branch</code> is
created and then dropped when it goes out of scope. The modifications are shown
in Listing 15-29.</p>
<figure class="listing" id="listing-15-29">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">use std::cell::RefCell;
</span><span class="boring">use std::rc::{Rc, Weak};
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Node {
</span><span class="boring"> value: i32,
</span><span class="boring"> parent: RefCell&lt;Weak&lt;Node&gt;&gt;,
</span><span class="boring"> children: RefCell&lt;Vec&lt;Rc&lt;Node&gt;&gt;&gt;,
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let leaf = Rc::new(Node {
value: 3,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![]),
});
println!(
"leaf strong = {}, weak = {}",
Rc::strong_count(&amp;leaf),
Rc::weak_count(&amp;leaf),
);
{
let branch = Rc::new(Node {
value: 5,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![Rc::clone(&amp;leaf)]),
});
*leaf.parent.borrow_mut() = Rc::downgrade(&amp;branch);
println!(
"branch strong = {}, weak = {}",
Rc::strong_count(&amp;branch),
Rc::weak_count(&amp;branch),
);
println!(
"leaf strong = {}, weak = {}",
Rc::strong_count(&amp;leaf),
Rc::weak_count(&amp;leaf),
);
}
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
println!(
"leaf strong = {}, weak = {}",
Rc::strong_count(&amp;leaf),
Rc::weak_count(&amp;leaf),
);
}</code></pre>
<figcaption><a href="#listing-15-29">Listing 15-29</a>: Creating <code>branch</code> in an inner scope and examining strong and weak reference counts</figcaption>
</figure>
<p>After <code>leaf</code> is created, its <code>Rc&lt;Node&gt;</code> has a strong count of 1 and a weak
count of 0. In the inner scope, we create <code>branch</code> and associate it with
<code>leaf</code>, at which point when we print the counts, the <code>Rc&lt;Node&gt;</code> in <code>branch</code>
will have a strong count of 1 and a weak count of 1 (for <code>leaf.parent</code> pointing
to <code>branch</code> with a <code>Weak&lt;Node&gt;</code>). When we print the counts in <code>leaf</code>, well see
it will have a strong count of 2 because <code>branch</code> now has a clone of the
<code>Rc&lt;Node&gt;</code> of <code>leaf</code> stored in <code>branch.children</code> but will still have a weak
count of 0.</p>
<p>When the inner scope ends, <code>branch</code> goes out of scope and the strong count of
the <code>Rc&lt;Node&gt;</code> decreases to 0, so its <code>Node</code> is dropped. The weak count of 1
from <code>leaf.parent</code> has no bearing on whether or not <code>Node</code> is dropped, so we
dont get any memory leaks!</p>
<p>If we try to access the parent of <code>leaf</code> after the end of the scope, well get
<code>None</code> again. At the end of the program, the <code>Rc&lt;Node&gt;</code> in <code>leaf</code> has a strong
count of 1 and a weak count of 0 because the variable <code>leaf</code> is now the only
reference to the <code>Rc&lt;Node&gt;</code> again.</p>
<p>All of the logic that manages the counts and value dropping is built into
<code>Rc&lt;T&gt;</code> and <code>Weak&lt;T&gt;</code> and their implementations of the <code>Drop</code> trait. By
specifying that the relationship from a child to its parent should be a
<code>Weak&lt;T&gt;</code> reference in the definition of <code>Node</code>, youre able to have parent
nodes point to child nodes and vice versa without creating a reference cycle
and memory leaks.</p>
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
<p>This chapter covered how to use smart pointers to make different guarantees and
trade-offs from those Rust makes by default with regular references. The
<code>Box&lt;T&gt;</code> type has a known size and points to data allocated on the heap. The
<code>Rc&lt;T&gt;</code> type keeps track of the number of references to data on the heap so
that the data can have multiple owners. The <code>RefCell&lt;T&gt;</code> type with its interior
mutability gives us a type that we can use when we need an immutable type but
need to change an inner value of that type; it also enforces the borrowing
rules at runtime instead of at compile time.</p>
<p>Also discussed were the <code>Deref</code> and <code>Drop</code> traits, which enable a lot of the
functionality of smart pointers. We explored reference cycles that can cause
memory leaks and how to prevent them using <code>Weak&lt;T&gt;</code>.</p>
<p>If this chapter has piqued your interest and you want to implement your own
smart pointers, check out <a href="../nomicon/index.html">“The Rustonomicon”</a> for more useful
information.</p>
<p>Next, well talk about concurrency in Rust. Youll even learn about a few new
smart pointers.</p>
</body>
</html>