rust学习十五.5、引用循环和内存泄露

打印 上一主题 下一主题

主题 890|帖子 890|积分 2670

这个章节主要是为了引出弱引用这个奇怪的概念。
说实在,这个没有什么太好写的,由于内容比力晦涩难明!
 
在其它语言中,也常常存在所谓循环引用题目,和大部分题目一样,在其它语言中这些根本上都不是题目。但是在rust中,这是一个致命的题目。
 
比方有a,b两个点,a指向b,b指向a。
假如根据截止当前的知识(全部权、一个数据也可以有多个全部者),那么rust可能无法释放a所实际指向的数据,或者是由于循环递归导致堆栈溢出。
或者其实我们也没有必要知道为什么,只要知道结论即可,究竟假如我们不看编译器是怎么写的。所以,有的时候就是看到了概念,看到了例子也是难以理解。
 
这些都需要借助于一些概念和例子来理解。
堆栈溢出示例(来自原书):
  1. use crate::List::{Cons, Nil};
  2. use std::cell::RefCell;
  3. use std::rc::Rc;
  4. #[derive(Debug)]
  5. enum List {
  6.     Cons(i32, RefCell<Rc<List>>),
  7.     Nil,
  8. }
  9. impl List {
  10.     fn tail(&self) -> Option<&RefCell<Rc<List>>> {
  11.         match self {
  12.             Cons(_, item) => Some(item),
  13.             Nil => None,
  14.         }
  15.     }
  16. }
  17. fn main() {
  18.     let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
  19.     println!("a initial rc count = {}", Rc::strong_count(&a));
  20.     println!("a next item = {:?}", a.tail());
  21.     let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
  22.     println!("a rc count after b creation = {}", Rc::strong_count(&a));
  23.     println!("b initial rc count = {}", Rc::strong_count(&b));
  24.     println!("b next item = {:?}", b.tail());
  25.     if let Some(link) = a.tail() {
  26.         *link.borrow_mut() = Rc::clone(&b);
  27.     }
  28.     println!("b rc count after changing a = {}", Rc::strong_count(&b));
  29.     println!("a rc count after changing a = {}", Rc::strong_count(&a));
  30.     // Uncomment the next line to see that we have a cycle;
  31.     // it will overflow the stack
  32.     // println!("a next item = {:?}", a.tail());
  33. }
复制代码
 
rust在做匹配的时候,会不停找尾巴,结果循着尾巴一直找.....
 
rust推出一个新的概念:弱引用(weak reference)
所谓弱引用,即指向某个数据,但是这种引用不会产生全部权方面的题目,就如同大部分其它语言那样的美好。
 
一、重要概念

Rc::downgradeRc::downgrade 会将 weak_count 加 1,同时返回Weak指针这个函数用于构建弱引用 Weak::upgrade()Weak 实例的 upgrade 方法,这会返回 Option 二、例子

书上例子很完善,稍微修改了下:
  1. use std::cell::RefCell;
  2. use std::rc::{ Rc, Weak };
  3. #[derive(Debug)]
  4. struct Node {
  5.     value: i32,
  6.     parent: RefCell<Weak<Node>>,
  7.     children: RefCell<Vec<Rc<Node>>>,
  8. }
  9. fn main() {
  10.     look_weak_ref();
  11. }
  12. fn look_weak_ref() {
  13.     let leaf = Rc::new(Node {
  14.         value: 3,
  15.         parent: RefCell::new(Weak::new()),
  16.         children: RefCell::new(vec![]),
  17.     });
  18.     println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));
  19.     {
  20.         println!("------------------------------------------------------------------------------");
  21.         let branch = Rc::new(Node {
  22.             value: 5,
  23.             parent: RefCell::new(Weak::new()),
  24.             children: RefCell::new(vec![Rc::clone(&leaf)]),
  25.         });
  26.         *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
  27.         println!("branch strong = {}, weak = {}",Rc::strong_count(&branch),Rc::weak_count(&branch));
  28.         println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));
  29.         println!("------------------------------------------------------------------------------");
  30.     }
  31.     println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
  32.     println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));
  33. }
复制代码

 
三、小结

假如我们成心构建导致堆栈溢出的死循环,还是可以的,书上也有这个例子。
但rust提供了可以避免这个的方法,究竟这种需求还是不鲜见的!
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表