use std::rc::Rc;
use std::cell::{RefCell};
#[derive(Debug)]
struct Node{
next:Option<Rc<RefCell<Node>>>,
}
fn main(){
let a=Rc::new(RefCell::new(Node{next:None}));
let b=Rc::new(RefCell::new(Node{next:Some(Rc::clone(&a))}));
let c=Rc::new(RefCell::new(Node{next:Some(Rc::clone(&b))}));
// we do not have any cycles so far
// after this line we have cycle. a-> b -> c -> a
(*a).borrow_mut().next=Some(Rc::clone(&c));
println!("a {:?}",a);
}
3条答案
按热度按时间2w3kk1z51#
是的,Rust中的内存泄漏就像调用
std::mem::forget
函数一样容易。如果创建shared references循环,也可能会发生内存泄漏:
Rc
指针之间的循环永远不会被释放。因此,Weak
用于中断循环。例如,树可能具有从父节点指向子节点的强Rc
指针,以及从子节点返回其父节点的Weak
指针。您还可以使用
Box::leak
创建静态引用,或者在FFI的情况下使用Box::into_raw
。实际上,在系统编程语言中,您 * 需要 * 能够创建内存泄漏,否则,例如在FFI的情况下,您的资源将在发送到另一种语言中使用后被释放。
所有这些例子都表明内存泄漏不会破坏Rust所保证的内存安全性。然而,可以安全地假设在Rust中,除非您做了非常具体的事情,否则不会发生任何内存泄漏。
另外,请注意,如果您采用内存泄漏的宽松定义,则有无数种方法可以创建内存泄漏,例如,在容器中添加一些数据,而不释放未使用的数据。
a5g8bdjr2#
从书上
Rust的内存安全保证使意外创建从未清理过的内存(称为内存泄漏)变得困难,但并非不可能。完全防止内存泄漏并不是Rust的保证之一,其方式与在编译时禁止数据竞争不同,这意味着内存泄漏在Rust中是内存安全的。
所以答案是肯定的,你的代码可能会有内存泄漏,而rust编译器不会抱怨。
lx0bsm1f3#
Rc
创建一个智能指针来计算引用。类似于垃圾收集器计算引用的方式。由于Rc
持有共享引用,因此它始终为immutable
Refcell
也是一个智能指针,它表示数据的单一所有权,但所有权规则是在运行时而不是编译时检查的。使用Refcell
,我们可以得到一个不变变量的可变引用。通常情况下,这是不允许的,因为x是不可变的,而我们得到的是一个可变的引用,但是使用
Refcell
我们得到了这个能力。通过将
Refcell
与Rc
Package 在一起,我们可以创建共享引用,该引用可以改变数据。在此介绍之后,此代码将创建内存泄漏:
当你打印“a”时,a指向B,b指向c,c又指向a,所以在终端会看到这样的情况:
您可以在这里阅读Reference Cycles Can Leak Memory