What does Rust have instead of a garbage collector?
我知道Rust没有垃圾回收器,我想知道当绑定超出范围时如何释放内存。
因此,在此示例中,我了解到Rust超出范围时,Rust回收分配给" a"的内存。
我遇到的问题是,首先是如何发生的,其次,这不是一种垃圾收集吗? 它与"典型"垃圾回收有何不同?
-
"确定性对象生存期"。 与C ++类似。
-
@ user2864740该指南已经过时了。 现代的替换可能是doc.rust-lang.org/book/references-and-borrowing.html。
垃圾收集通常是定期或按需使用的,例如,如果堆接近满或超过某个阈值。然后,根据算法,查找未使用的变量并释放它们的内存。
Rust会知道变量何时超出范围或其生存期在编译时结束,因此插入相应的LLVM / assembly指令以释放内存。
Rust还允许某种垃圾收集,例如原子引用计数。
-
通过在引入变量时分配内存并在不再需要内存时释放内存?我真的不知道你想怎么说。也许我们对当时的GC有不同的看法。
-
他的问题是Rusts方法与典型的GC有何不同。因此,我解释了什么是GC以及Rust在没有GC的情况下是如何做到的。
-
我是否认为如果仅使用let创建对象,就会在堆栈上创建对象,这是错误的吗?不需要垃圾收集吗?当然,如果没有在其ctor中分配某些内容。
-
doc.rust-lang.org/book/the-stack-and-the-heap.html解释得很好。是的,很多东西都在堆栈中,但更不用说这是不够的指标(请参见方框)。为了简单起见,我忽略了这一点,因为尽管
-
@Ayonix谢谢,我只是想检查一下我的理智,在Rust中,我们需要显式调用某种new()来在堆上分配。
-
@Amomum实际上Rust并没有像C这样受膏的new()函数,它们只是静态函数,尤其是像let x = MyStruct::new()这样的东西会在堆栈上创建其对象。堆分配的真正指标是Box::new()(或任何依赖Box的结构)。
-
还有哪些其他语言以与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本身关联的内存缓冲区
因此,由于所有权跟踪,所有程序对象的生存期都严格地与一个(或几个)函数变量联系在一起,这些变量最终将超出范围(当它们属于的块结束时)。
注意:这有点乐观,使用引用计数(Rc或Arc)可以形成引用循环,从而导致内存泄漏,在这种情况下,与循环相关的资源可能永远不会释放。
-
"带有垃圾收集器的语言会定期(一种或另一种方式)扫描内存"。许多人这样做,但总的来说是不正确的。实时垃圾收集器将进行增量扫描,而不是定期扫描。引用计数语言(如Mathematica)根本不会扫描。
-
@JonHarrop:我不将引用计数视为完整的垃圾收集机制,因为必须对其进行补充以避免泄漏周期。至于渐进式/周期性的差异,可能是我的英语水平不佳,但我看不到周期性如何无法涵盖渐进式的情况...我认为"(一种或另一种)"位足以传达出许多变化存在方法。无论如何,如果您有一个更好地简洁描述垃圾收集的方法,请提出建议。但是,我无意以全面的解释发动自己:我对此没有资格。
-
"我不将引用计数视为完整的垃圾收集机制,因为必须对其进行补充以避免泄漏周期"。 RC通常被视为GC的一种形式。例如,在Mathematica和Erlang中,无法通过设计创建周期,因此RC不会泄漏。有关高级观点,请参见"垃圾收集的统一理论" cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
-
@JonHarrop:是的,如果没有循环可能,那么RC就不会泄漏。
-
"我看不到定期如何不能涵盖增量案件"。例如,停止世界算法将被视为周期性算法,而三色标记将被视为增量算法。在这种情况下,它们是相反的。
使用必须手动管理内存的语言,堆栈和堆之间的区别就变得至关重要。每次调用函数时,都会在堆栈上为该函数范围内包含的所有变量分配足够的空间。当函数返回时,与该函数关联的堆栈帧从堆栈中"弹出",并且释放内存以供将来使用。
从实际的角度来看,这种无意中的内存清理被用作自动内存存储的一种方式,该功能将在功能范围的末尾清除。
这里有更多信息:
https://doc.rust-lang.org/book/the-stack-and-the-heap.html
-
尽管使用堆栈很方便,但是如果在堆上创建了所有值,则仍然可以处理确定性对象的生存期。因此,这是一个实现细节;不一定是语言策略。
-
你一直在用那个词。我认为这并不意味着您认为的意思。
-
表示我想表达的意思;与不确定性寿命相反。提出一个更好的短语。
-
感谢您的回答,我只因为第一个提交了它们,所以给了第一个分数。这些信息同样有用和有效。
-
@ user2864740确定性对象生存期指的是能够准确告知一旦调用析构函数的对象内存将被清除的时间。它与该析构函数的调用方式无关。即使对这个问题没有直接意义,您仍会反复提出相同的术语。