Rust有什么代替垃圾收集器?

What does Rust have instead of a garbage collector?

我知道Rust没有垃圾回收器,我想知道当绑定超出范围时如何释放内存。

因此,在此示例中,我了解到Rust超出范围时,Rust回收分配给" a"的内存。

1
2
3
{
    let a = 4
}

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


垃圾收集通常是定期或按需使用的,例如,如果堆接近满或超过某个阈值。然后,根据算法,查找未使用的变量并释放它们的内存。

Rust会知道变量何时超出范围或其生存期在编译时结束,因此插入相应的LLVM / assembly指令以释放内存。

Rust还允许某种垃圾收集,例如原子引用计数。


无论采用何种策略,在程序中管理资源(包括内存)的基本思想是可以回收与无法访问的"对象"相关的资源。除了内存之外,这些资源还可以是互斥锁,文件句柄,套接字,数据库连接...

具有垃圾收集器的语言会定期(一种或另一种方式)扫描内存以查找未使用的对象,释放与它们相关的资源,最后释放那些对象使用的内存。

Rust没有GC,它如何管理?

Rust具有所有权。使用仿射类型系统,它跟踪哪个变量仍保留在对象上,并在此类变量超出范围时调用其析构函数。您可以很容易地看到仿射类型系统生效:

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

产量:

1
2
3
4
5
6
:4:24: 4:25 error: use of moved value: `s` [E0382]
:4         println!("{}", s);

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

这完美地说明了在语言水平的任何时间点,所有权都是可以跟踪的。

这种所有权是递归的:如果您有一个Vec(即一个动态字符串数组),则每个String都由Vec拥有,而Vec本身又由一个变量或另一个对象等拥有,因此... ,当变量超出范围时,它将以递归方式释放其持有的所有资源,甚至是间接释放。对于Vec,这意味着:

  • 释放与每个String关联的内存缓冲区
  • 释放与Vec本身关联的内存缓冲区
  • 因此,由于所有权跟踪,所有程序对象的生存期都严格地与一个(或几个)函数变量联系在一起,这些变量最终将超出范围(当它们属于的块结束时)。

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


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

    从实际的角度来看,这种无意中的内存清理被用作自动内存存储的一种方式,该功能将在功能范围的末尾清除。

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