c++ - 在 C++0x 中压缩垃圾收集器的实现

标签 c++ garbage-collection c++11

我正在 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/

相关文章:

c++ - 如何从 lambda-functor 的主体中增加一个变量?

c++ - 让 Windows 10 旁白者说出一些文字

java - 本地字符串文字的内存分配?

Java 8 字符串垃圾收集

c++ - 具有自定义删除器的智能指针作为类成员

c++ - 使用 std c++11 中的 Boost Test Unit 进行编译

c++ - 尝试学习 C++ 中的数据结构时不熟悉 C++ 语法

c++ - 二叉树(不是二叉搜索树)创建新节点和子节点

c# - 如果不是启动项目,如何在 C++ 应用程序中打断点

java - 增加 Android 应用程序中的初始可用内存量