# Memory Leaks in Reference Cycles Making inifinite references like used with `Rc` or `RefCell`, can create memory leaks if they reference each other. ## Creating Reference cycles Updating the List example ```rust #[derive(Debug)] enum List { Cons(i32, RefCell>), Nil, } impl List { fn tail(&self) -> Option<&RefCell>> { match self { Cons(_, item) => Some(item), Nil => None, } } } ``` We want to be able to change which List is pointing `Rc` to, so `RefCell>` We can make, list `a` and `b` point to `a`, then make `a` point to `b` using the `tail()` method -> Reference Cycle. The following main will run, but the commented print would overflow as it will cyclycally go through `a` and `b` to print all the items on the list! ```rust 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()); } ``` At the end of the program, `b` drops 1 reference, but a references it to, so it goes from 2 references to 1 Same goes to `a` which will be dropped by 1, but was 2 because `b` referenced it but did not drop it. Solution: Make some references non-owning an dother have it. Owners will drop entirely the value instead of counts. That is invalid in our example, we need ownership of the references for each one. ## Preventing Reference Cycles -> `Weak` Using `Rc::clone()` increases `strong_count` of references. The value will only be cleaned up if `strong_count == 0`. `Rc::downgrade() -> Weak` : Increases `weak_count` by 1, which does not need to be 0 to be cleaned up. Strogn reference share ownership, weak referencees don't. To access value from `Weak` -> `Weak::upgrade()` -> Checks if the value is still valid and retursn `Option>`. ### Example: Tree Data Structure ```rust use std::rc::{Rc, Weak}; #[derive(Debug)] struct Node { value: i32, parent: RefCell>, children: RefCell>>, } fn nodes() { let leaf = Rc::new(Node { value: 3, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![]), }); let branch = Rc::new(Node { value: 5, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![Rc::clone(&leaf)]), }); *leaf.parent.borrow_mut() = Rc::downgrade(&branch); println!("Leaf parentL {:#?}", leaf.parent.borrow().upgrade()); } ``` `Node` owns the reference to each of the childrens(`Rc`), but can change who owns them (RefCell, which allows mutability of the vector). We also want the node, to know who is its parent, but not own them, thus `Weak` because it does not own, and the parent might change so `RefCell`. In the main, we create each node without a parent, then we `borrow_mut` the leaf's parent and change it to the downgraded reference of `branch` variable. ### Visualizing Counts ```rust fn nodes() { let leaf = Rc::new(Node { value: 3, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![]), }); println!( "leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf), ); // Leaf strong owns the node as itself { let branch = Rc::new(Node { value: 5, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![Rc::clone(&leaf)]), // Branch strong owns the leaf node as child }); // Branch strong owns branch node as itself *leaf.parent.borrow_mut() = Rc::downgrade(&branch); // Leaf weak owns the branch node as parent println!( "branch strong = {}, weak = {}", Rc::strong_count(&branch), Rc::weak_count(&branch), ); // Branch owned 1 time strongly by itself, 1 time weakly by leaf println!( "leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf), ); // Leaf owned 2 times strongly by itself and branch, 0 times weakly } // Branch is dropped as only itself had strong ownership (Reference ot 0), 1 strong own of leaf is dropped, leaf still owns weakly branch as parent println!("leaf parent = {:?}", leaf.parent.borrow().upgrade()); // Call upgrade to check borrow parent, as it returns None, the weak ownership is now dropped to branch println!( "leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf), ); // Leaf has 1 strong ownership of itself, 0 weak references by anyone. } ```