我正在 C++0x 中实现一个压缩垃圾收集器供我个人使用,我有一个问题。显然,收集器的机制取决于移动对象,我一直想知道如何根据指向它的智能指针类型来实现这一点。我一直在考虑指针类型本身中的指针指向指针,或者收集器维护一个指向每个对象的指针列表,以便可以修改它们,从而在访问时不需要双重取消引用指针,但在收集过程中增加了一些额外的开销和额外的内存开销。去这里的最佳方式是什么?
编辑:我主要关心的是快速分配和访问。我不关心特别有效的收集或其他维护,因为这并不是 GC 的真正用途。
最佳答案
将额外的 GC 移植到 C++ 并没有什么直接的方法,更不用说压缩算法了。目前尚不清楚您正在尝试做什么以及它将如何与其他 C++ 代码交互。
我实际上已经用 C++ 编写了一个 gc,它可以与现有的 C++ 代码一起使用,并且它在一个阶段有一个压缩器(尽管我放弃了它,因为它太慢了)。但是有许多令人讨厌的语义问题。几周前我向 Bjarne 提到过,C++ 缺少正确执行此操作所需的运算符,而且情况是它不太可能存在,因为它的实用性有限..
你真正需要的是一个“re-address-me”操作符。发生的情况是您实际上并没有移动对象。您只需使用 mmap 更改对象地址。这要快得多,实际上,它使用 VM 功能来提供句柄。
如果没有此功能,您必须有一种方法来执行对象的重叠 移动,而这在 C++ 中无法有效执行:您必须首先移动到临时对象。在 C 语言中,这要容易得多,您可以使用 memmove
。在某个阶段,必须调整所有指向或进入移动对象的指针。
使用句柄不能解决这个问题,它只是将问题从任意大小的对象减少到恒定大小的对象:这些在数组中更容易管理,但同样的问题存在:你必须管理存储。如果您从数组中随机删除大量句柄..您仍然会遇到碎片问题。
所以不要打扰 handle ,它们不起作用。
这就是我在 Felix 中所做的:你调用 new(shape, collector) T(args)
。这里的 shape
是类型的描述符,包括一个包含 (GC) 指针的偏移量列表,以及用于完成对象的例程的地址(默认情况下,它调用析构函数)。
它还包含一个标志,说明是否可以使用 memmove
移动对象。如果对象很大或无法移动,则由 malloc
分配。如果对象很小且可移动,则将其分配在一个竞技场中,前提是该竞技场中有空间。
通过移动其中的所有对象来压缩竞技场,并使用形状信息全局调整指向或进入这些对象的所有指针。压缩可以增量完成。
C++ 程序员的缺点是需要构造一个正确的 shape
对象来传递。这并不困扰我,因为我正在实现一种可以自动生成形状信息的语言。
现在:关键点是:要进行压缩,您必须使用精确的收集器。压缩不能与保守的收集器一起使用。这个非常重要。如果你看到一个看起来像指针但恰好是整数的值,允许一些泄漏是可以的:一些对象不会被收集,但这通常没什么大不了的。但是对于压缩,你必须调整指针,但你最好不要改变那个整数:所以你必须知道确定什么时候是指针,所以你的收集器有准确地说:形状必须是已知的。
在 Ocaml 中,这相对简单:一切都是指针或整数,低位在运行时用于指示。指向的对象有一个代码告诉类型,并且只有几种类型:标量(不要扫描它)或聚合(扫描它,它只包含整数或指针)。
关于c++ - 在 C++0x 中压缩垃圾收集器的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4558473/