除了垃圾收集器 Rust 还有什么?

我知道 Rust 没有垃圾收集器,我想知道当绑定超出作用域时如何释放内存。

因此在本例中,我理解 Rust 在超出作用域时回收分配给 a的内存。

{
let a = 4
}

我的问题是,首先,这是怎么发生的,其次,这不是一种垃圾收集吗?它与 typical垃圾收集有什么不同?

69653 次浏览

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

从实际的角度来看,这种意外的内存清理被用作自动内存存储的一种方法,这种方法将在函数作用域结束时被清除。

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

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

Rust 会知道变量什么时候超出作用域或者它的生命周期在编译时结束,从而插入相应的 LLVM/汇编指令来释放内存。

Rust 还允许某种类型的垃圾收集,比如 原子参考计数原子参考计数

管理程序中的资源(包括内存)的基本思想是,无论采用什么策略,绑定到不可到达的“对象”的资源都可以被回收。除了内存,这些资源可以是互斥锁、文件句柄、套接字、数据库连接..。

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

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

铁锈有所有权。它使用 仿射型系统仿射型系统跟踪哪个变量仍然保留在对象上,当这个变量超出作用域时,调用它的析构函数。你可以很容易地看到仿射类型系统的效果:

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>而言,这意味着:

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

因此,由于所有权跟踪,所有程序对象的生命周期都严格地绑定到一个(或多个)函数变量,这些变量最终将超出作用域(当它们属于块结束时)。

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

有些语言有引用计数,有些语言有垃圾收集器。 相反,如果您希望在任何时候都拥有一个内存位置,Rust 可以避免这两种情况,它只允许使用单个变量名或别名。你可以移动 从一个变量名称到另一个变量名称的所有权,但是不能让两个变量名称指向相同的内存地址(除了共享所有权。Rust 提供了引用计数的指针类型 Rc 和 Arc。因为有时很难找到一个拥有您所需的生命周期的单个所有者的每个值)。

Rust 使用一种相对独特的内存管理方法 结合了内存“所有权”的概念 跟踪谁可以读写内存。它知道当程序 正在使用内存,一旦内存不再使用,就会立即释放内存 它在编译时强制执行内存规则,使其虚拟化 不可能存在运行时内存错误 记录内存,由编译器负责。

Discord 最近在其一项服务中从 Go 转向 Rust,仅仅是因为垃圾收集器造成了延迟。他们很好地解释了为什么要这样做,您将了解更多关于垃圾收集器和生锈内存系统的信息:

Https://discord.com/blog/why-discord-is-switching-from-go-to-rust#:~:text=discord%20is%20a%20product%20focused,and%20messages%20you%20have%20read.