-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Hi,
As a beginner, I recently got confused when reading the chapter about reference cycles:
https://doc.rust-lang.org/stable/book/ch15-06-reference-cycles.html
fn main() {
let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
println!("a initial rc count = {}", Rc::strong_count(&a));
println!("a next item = {:?}", a.tail());
let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
println!("a rc count after b creation = {}", Rc::strong_count(&a));
println!("b initial rc count = {}", Rc::strong_count(&b));
println!("b next item = {:?}", b.tail());
if let Some(link) = a.tail() {
*link.borrow_mut() = Rc::clone(&b);
}
println!("b rc count after changing a = {}", Rc::strong_count(&b));
println!("a rc count after changing a = {}", Rc::strong_count(&a));
// Uncomment the next line to see that we have a cycle;
// it will overflow the stack
// println!("a next item = {:?}", a.tail());
}
I found the representation of this cycle to be a bit misleading considering that it is later mentioned that the variables a
and b
are dropped at the end of the scope.
However, if we base ourselves solely on this graph, if somehow a
and b
are dropped then we shouldn't be left with a cycle?
My understanding is that a
and b
are Rc
; and these variables are indeed dropped (i.e. the count of the managing shared pointers is decreased from 2
to 1
).
However, the values these Rc
were pointing to are not cleaned up since what is essentially left over is trapped in a cycle between two Rc
of count 1
.
I could be wrong, but I had something closer to this representation in my mind by looking at the code:
I went on #rust-beginners
because I thought I was missing something, and the person I ended up talking to seemed to agree that there was a potential issue here.
PS: The .dot
file for this cycle graph seems to be missing, I created the above graph with the following .dot
file.
digraph {
node[shape=record];
rankdir=LR;
l1[label="{<data> 5| <next>}"];
l2[label="{<data> 10| <next>}"];
{node[shape=point height=0] invisible_start invisible_end}
a -> l1:n;
b -> l2:n;
invisible_start:n -> l1[arrowtail=none];
invisible_start:s -> invisible_end:s[dir=none];
l1:next:c -> l2:data;
l2:next:c -> invisible_end:n[arrowhead=none];
}