Rust有什么而不是垃圾收集器?

我理解Rust没有垃圾收集器,并且想知道当绑定超出范围时如何释放内存 .

所以在这个例子中,我理解Rust在超出范围时回收分配给'a'的内存 .

{
    let a = 4
}

我遇到的问题首先是如何发生这种情况,其次这不是一种垃圾收集?它与“典型”垃圾收集有何不同?

回答(3)

3 years ago

无论策略如何,管理程序中资源(包括内存)的基本思想是可以回收与无法访问的“对象”相关的资源 . 超越内存,这些资源可以是互斥锁,文件句柄,套接字,数据库连接......

带有垃圾收集器的语言会定期扫描内存(以某种方式)查找未使用的对象,释放与之关联的资源,最后释放这些对象使用的内存 .

Rust没有GC,它是如何管理的?

Rust拥有所有权 . 使用affine type system,它跟踪哪个变量仍然保留在对象上,当这样的变量超出范围时,调用它的析构函数 . 您可以非常轻松地看到仿射类型系统:

fn main() {
    let s: String = "Hello, World!".into();
    let t = s;
    println!("{}", s);
}

产量:

<anon>:4:24: 4:25 error: use of moved value: `s` [E0382]
<anon>:4         println!("{}", s);

<anon>:3:13: 3:14 note: `s` moved here because it has type `collections::string::String`, which is moved by default
<anon>:3         let t = s;
                     ^

这完美地说明了在任何时间点,在语言层面,都会跟踪所有权 .

这种所有权递归地工作:如果你有一个 Vec<String> (即一个动态的字符串数组),那么每个 String 都归 Vec 所有, Vec 本身由一个变量或另一个对象等拥有......因此,当一个变量熄灭时范围,它递归地释放它所持有的所有资源,甚至是间接的 . 在 Vec<String> 的情况下,这意味着:

  • 释放与每个 String 关联的内存缓冲区

  • 释放与 Vec 本身关联的内存缓冲区

因此,由于所有权跟踪,所有程序对象的生命周期严格依赖于一个(或几个)函数变量,这些函数变量最终将超出范围(当它们所属的块结束时) .

注意:这有点乐观,使用引用计数( RcArc )可能会形成引用循环,从而导致内存泄漏,在这种情况下,可能永远不会释放与循环相关的资源 .

3 years ago

垃圾收集通常定期或按需使用,例如堆接近满或高于某个阈值 . 然后它会查找未使用的变量并释放它们的内存,具体取决于algorithm .

Rust会知道变量何时超出范围或其生命周期在编译时结束,从而插入相应的LLVM /汇编指令以释放内存 .

Rust也允许某种垃圾收集,比如atomic reference counting .

3 years ago

使用必须手动管理内存的语言,堆栈和堆之间的区别变得至关重要 . 每次调用函数时,都会在堆栈上为该函数范围内包含的所有变量分配足够的空间 . 当函数返回时,与该函数关联的堆栈帧从堆栈“弹出”,并释放内存以供将来使用 .

从实际角度来看,这种无意的内存清理用作自动内存存储的一种方法,将在功能范围结束时清除 .

这里有更多信息:https://doc.rust-lang.org/book/the-stack-and-the-heap.html