是否可能导致Rust中的内存泄漏?

xt0899hw  于 2023-01-17  发布在  其他
关注(0)|答案(3)|浏览(375)

有没有什么方法可以在Rust中造成内存泄漏?我知道即使是像JavaScript这样的垃圾收集语言也有内存泄漏的边缘情况,Rust中有这样的情况吗?

2w3kk1z5

2w3kk1z51#

是的,Rust中的内存泄漏就像调用std::mem::forget函数一样容易。
如果创建shared references循环,也可能会发生内存泄漏:
Rc指针之间的循环永远不会被释放。因此,Weak用于中断循环。例如,树可能具有从父节点指向子节点的强Rc指针,以及从子节点返回其父节点的Weak指针。
您还可以使用Box::leak创建静态引用,或者在FFI的情况下使用Box::into_raw
实际上,在系统编程语言中,您 * 需要 * 能够创建内存泄漏,否则,例如在FFI的情况下,您的资源将在发送到另一种语言中使用后被释放。
所有这些例子都表明内存泄漏不会破坏Rust所保证的内存安全性。然而,可以安全地假设在Rust中,除非您做了非常具体的事情,否则不会发生任何内存泄漏。
另外,请注意,如果您采用内存泄漏的宽松定义,则有无数种方法可以创建内存泄漏,例如,在容器中添加一些数据,而不释放未使用的数据。

a5g8bdjr

a5g8bdjr2#

从书上
Rust的内存安全保证使意外创建从未清理过的内存(称为内存泄漏)变得困难,但并非不可能。完全防止内存泄漏并不是Rust的保证之一,其方式与在编译时禁止数据竞争不同,这意味着内存泄漏在Rust中是内存安全的。
所以答案是肯定的,你的代码可能会有内存泄漏,而rust编译器不会抱怨。

lx0bsm1f

lx0bsm1f3#

use std::rc::Rc;
use std::cell::{RefCell};

Rc创建一个智能指针来计算引用。类似于垃圾收集器计算引用的方式。由于Rc持有共享引用,因此它始终为immutable
Refcell也是一个智能指针,它表示数据的单一所有权,但所有权规则是在运行时而不是编译时检查的。使用Refcell,我们可以得到一个不变变量的可变引用。

let x=32;
let x1=&mut x;

通常情况下,这是不允许的,因为x是不可变的,而我们得到的是一个可变的引用,但是使用Refcell我们得到了这个能力。
通过将RefcellRc Package 在一起,我们可以创建共享引用,该引用可以改变数据。
在此介绍之后,此代码将创建内存泄漏:

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);
}

当你打印“a”时,a指向B,b指向c,c又指向a,所以在终端会看到这样的情况:

您可以在这里阅读Reference Cycles Can Leak Memory

相关问题