我看到垃圾收集器被标记为很多东西 - 世代等等。但我看到Boehm GC标记为“保守”。究竟是什么意思?
答案 0 :(得分:25)
垃圾收集器必须扫描所有对象和调用(执行堆栈)以识别正在执行的程序中的所有“实时”地址,然后“收集”没有“实时”地址的对象。在某些环境中,GC算法可能是精确的,并且确切地知道什么是对象地址,什么不是。在其他环境中,它必须扫描存储的部分(最明显的是执行堆栈),其中存在可能是对象地址的存储字,并使CONSERVATIVE假设它看起来像一个有效的地址,并且有一个对象具有该地址地址,然后不应该收集对象。
保守集合有一些优点,最值得注意的是代码生成器(如果不解释)更自由地在需要的地方和时间分配变量,并且不需要严格跟踪哪些是对象指针。 (除了使代码生成器更加复杂之外,跟踪对象指针位置的需要可能导致代码不太优化。此外,保守的收集器有一定的合理机会与编译器一起使用,而编译器从未打算支持垃圾收集,而精确的收集器则需要彻底改变编译器。)
保守方法的主要缺点是无法实现完整的“复制”收集器。复制完成后,必须更新指向复制对象的指针,如果不清楚给定的位值是对象指针还是仅仅是数值,则无法确定当对象是否应该修改它时是否应该修改它。复制。还有一个缺点是,由于随机位模式看起来像他们的地址,一些“死”对象最终可能无法收集,但实际上这并不是一个严重的问题。
答案 1 :(得分:6)
保守垃圾收集器是指不知道给定单词是否为指针的收集器。如果单词指向一个已分配的堆块,那么垃圾收集器会保守地假定该单词是一个指针,因此不会回收该堆块或任何被认为可以从中获取的内容。
这种方法的主要优点是它可以收集无法访问的值,而无需与编译器协调工作。但是,有许多缺点:
碰巧看起来像指针的值会导致内存泄漏,从而阻止堆的某些部分被回收。对于32位地址空间来说,这是一个更大的问题,因为如果已经分配了GB的GB,几乎每个int都会指向一个堆块。
确定一个单词是否指向已分配的堆块需要搜索堆,这很慢并且(客观上)是不必要的。
GC无法移动堆块,因为它无法更新指针,因为它不知道它们的位置。
隐藏指针或使用堆块外部指针的代码会使保守的GC崩溃。这个问题出现在Numerical Recipes代码和Boehm GC中,尽管因为NR C代码违反了C规范。
这些缺点非常严重,生产垃圾收集者尽可能不保守。