使用 RefCell 和 Rc 处理循环图中的内存泄漏
Posted
技术标签:
【中文标题】使用 RefCell 和 Rc 处理循环图中的内存泄漏【英文标题】:Handling memory leak in cyclic graphs using RefCell and Rc 【发布时间】:2018-05-29 02:04:09 【问题描述】:我按照https://ricardomartins.cc/2016/06/08/interior-mutability 中提到的方法使用Rc
和RefCell
在Rust 中创建图形。
type NodeRef<i32> = Rc<RefCell<_Node<i32>>>;
#[derive(Clone)]
// The private representation of a node.
struct _Node<i32>
inner_value: i32,
adjacent: Vec<NodeRef<i32>>,
#[derive(Clone)]
// The public representation of a node, with some syntactic sugar.
struct Node<i32>(NodeRef<i32>);
impl<i32> Node<i32>
// Creates a new node with no edges.
fn new(inner: i32) -> Node<i32>
let node = _Node inner_value: inner, adjacent: vec![] ;
Node(Rc::new(RefCell::new(node)))
// Adds a directed edge from this node to other node.
fn add_adjacent(&self, other: &Node<i32>)
(self.0.borrow_mut()).adjacent.push(other.0.clone());
#[derive(Clone)]
struct Graph<i32>
nodes: Vec<Node<i32>>,
impl<i32> Graph<i32>
fn with_nodes(nodes: Vec<Node<i32>>) -> Self
Graph nodes: nodes
我认为这种方法在循环图的情况下会导致内存泄漏。我该如何解决?
【问题讨论】:
【参考方案1】:您无需阅读博文即可找到答案,只需read the documentation:
Rc
指针之间的循环永远不会被释放。出于这个原因,Weak
用于中断循环。例如,一棵树可能具有从父节点到子节点的强Rc
指针,以及从子节点返回父节点的Weak
指针。
另见:
Is there a way to build a structure with cyclic links without runtime overhead? Implement graph-like datastructure in Rust Recursive Data Structures in Rust【讨论】:
嗯,这是否意味着对于您插入的每条边,您将查看整个图形以检查这条边是否会创建一个循环?我确实读过,如果您希望孩子指向父母,您可以在树中使用弱指针。但我不知道在图表的情况下如何翻译?图中的弱指针是什么意思? @user9097180 您即将开始探索为什么在垃圾回收和非 GC 语言中,究竟图对于内存管理来说是非常困难的概念。如果您(人类)无法确定一个过程来确定图中哪些链接是强链接,哪些链接是弱链接,那么编译器/运行时将如何?也许如果您的节点有一些排序,您可以为“较大”节点做强引用,为“较小”节点做弱引用(我不知道这是否可行)。 @user9097180:此时,您可能需要查找petgraph
crate。以上是关于使用 RefCell 和 Rc 处理循环图中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章
Rc<RefCell<T>> 和 RefCell<Rc<T>> 有啥区别?
Rayon 如何防止线程之间使用 RefCell<T>、Cell<T> 和 Rc<T>?