我们为什么不让编译器在适当的地方自动插入 free(),而不是在运行时定期运行垃圾检测?这样,我们只需在编译时支付一次价格。
编译器知道变量超出范围或重新分配给不同对象的位置。因此,它可以找出该对象是否不再可达,并在那里自动插入 free()。
不可以吗?为什么?
如果是多线程的原因,那我们可以用单线程/绿色线程的语言来做吗?
最佳答案
The compiler knows the places where a variable goes out of scope or gets reassigned to different object.
当然可以 - 对于变量。但是你不清除变量 - 你清除它们指向的内存。仅仅因为变量超出范围,并不意味着指向的内存不再可达。
例如:
y = ...
{
x = new X();
if (todayIsTuesday()) {
y = x;
}
} // x just went out of scope
您无法在编译时决定是否应在该段的最后一行释放 x 指向的内存,因为这取决于代码运行时是星期几 .
所以为了解决这个问题,这个决定必须委托(delegate)给运行时,通过插入适当的逻辑,例如:
Y* y = ...
{
X* mem = new X();
X* x = mem;
markPointer(&x, mem);
if (todayIsTuesday()) {
y = x;
markPointer(&y, mem);
}
markNoLongerPointer(&x, mem);
} // x just went out of scope
如果内部维护的数据结构告诉它 x
是对该内存的唯一引用,则使用 markNoLongerPointer()
清除作为第二个参数给出的内存...换句话说,这是引用计数逻辑的粗略起点。
编译器当然可以将这样的引用计数逻辑添加到编译后的代码中,有些确实如此,但正如其他人所提到的,引用计数有一些缺点:高开销、循环问题,加上它有时会在不方便的时候导致严重的暂停,当对大型数据结构的根的唯一引用超出范围时。虽然有一些方法可以解决其中的一些缺点,但这超出了这个答案的范围:-)
关于compiler-construction - 为什么要收集垃圾?为什么编译器不自动插入 free() 呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34915554/