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

时间:2015-09-20 08:37:31

标签: rust

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

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

{
    let a = 4
}

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

3 个答案:

答案 0 :(得分:57)

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

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

Rust还允许某种垃圾收集,例如atomic reference counting

答案 1 :(得分:37)

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

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

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<String>本身由变量拥有或者另一个对象等...因此,当一个变量超出范围时,它会递归地释放它所拥有的所有资源,甚至间接地释放它。在String的情况下,这意味着:

  1. 释放与每个Vec
  2. 关联的内存缓冲区
  3. 释放与Rc本身
  4. 关联的内存缓冲区

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

    注意:这有点乐观,使用引用计数(ArcAddress address = new Address(); address.setStreet1(""); address.setStreet2(""); address.setZipCode(""); address.setId(1234); StopWatch stopWatch = new StopWatch(); stopWatch.start(); IntStream.iterate(0, i -> i++).limit(1000000).parallel(). forEach(i -> addressRepository.insert(address); stopWatch.stop(); )可能会形成引用循环,从而导致内存泄漏,在这种情况下资源被绑定可能永远不会释放循环。

答案 2 :(得分:6)

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

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

此处提供了更多信息: https://doc.rust-lang.org/book/the-stack-and-the-heap.html