compiler-construction - 为什么要收集垃圾?为什么编译器不自动插入 free() 呢?

标签 compiler-construction garbage-collection

我们为什么不让编译器在适当的地方自动插入 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/

相关文章:

memory-management - 想知道没有人引用的自动数据删除

c++ - 引擎 Matlab 问题

parsing - Bison 减少/减少与强制转换和表达式括号的冲突

linux - 如何告诉 "gmake"使用另一个版本的 GCC? (Linux)

mysql - 关于 MySQL 表上的垃圾收集/自动删除的问题

python - 调试 Python C 扩展模块中的引用计数内存泄漏

C# 4.0 编译器崩溃

C++。如何知道方法/变量的定义位置?或者如何询问编译器?

javascript - 我可以从开发工具中获取 GC 的内存吗?

git - 理解 git gc --auto