C++ 垃圾回收

Posted

技术标签:

【中文标题】C++ 垃圾回收【英文标题】:C++ garbage collection 【发布时间】:2021-12-20 19:08:41 【问题描述】:

有许多用于 C++ 的垃圾回收库。

我有点困惑指针跟踪的工作原理。

特别是,假设我们有一个基指针 P 和一个其他指针列表,这些指针使用数组计算为 P 的偏移量。

前,

P2 = P+偏移量[0]

垃圾收集器如何知道 P2 仍在作用域内?它没有直接引用,但仍然可以访问。

可能最流行的 C++ gc 是

https://en.m.wikipedia.org/wiki/Boehm_garbage_collector

但是按照他们的示例语法,它似乎很容易被破解,所以我一定不明白。

【问题讨论】:

为什么你认为它不知道PP2 是同一个对象? 请添加具体库和minimal reproducible example 数组中的每一项都可以是 shared_ptr 或类似的,数组内存本身是私有的,不能直接访问。 P[offset[0]] 将返回 shared_ptr。 垃圾收集器知道每个对象(包括数组)的大小。就 GC 而言,指向对象内任何地址的指针都是指向该对象的指针。 【参考方案1】:

这个问题不能笼统地回答。有不同的系统可以被视为 C++ 的垃圾收集;例如,Herb Sutter's deferred_ptr 基本上是一个垃圾收集智能指针。我个人实现了another version of this idea,类似于 Sutter 的但不那么花哨。

不过,我可以回答有关 Boehm 的问题。 Boehm 垃圾收集器在其“标记”阶段如何识别指针,基本上是通过扫描内存并假设看起来像指针的东西是指针。

垃圾收集器知道用户数据所在的所有内存区域,它知道它已分配的所有指针以及这些分配的大小。它只是查找从定义如下的“根段”开始的指针链,其中“查找”是指显式扫描内存以查找与它已完成的 GC 分配之一相同的 64 位值。

来自here:

由于它通常不能告诉指针变量的位置,它 扫描以下根段以查找指针:

寄存器。根据体系结构,这可以使用汇编代码来完成,或者通过调用类似 setjmp 的函数来完成 将寄存器内容保存在堆栈中。 堆栈。对于单线程应用程序,在大多数平台上,这是通过扫描 (an 当前堆栈指针和 GC_stackbottom 的近似值。 (对于 Itanium,寄存器堆栈单独扫描。)GC_stackbottom 变量以高度特定于平台的方式设置,具体取决于 gcconfig.h 中的适当配置信息。请注意, 当前活动的堆栈需要仔细扫描,因为 客户端代码的被调用者保存寄存器可能会出现在收集器中 堆栈帧,在标记过程中可能会发生变化。这是 通过“急切地”扫描堆栈的某些部分来解决, 在某个时间点有效地捕捉快照。 静态数据区域。在最简单的情况下,这是 DATASTART 和 DATAEND 之间的区域,如 gcconfig.h 中所定义。然而,在 大多数情况下,这也将涉及关联的静态数据区域 与动态库。这些主要由 dyn_load.c 中特定于平台的代码。

64 位指针的地址空间很大,因此误报很少见,但即使发生,误报也只是泄漏,只要内存中碰巧有其他变量标记阶段扫描的值与垃圾收集器分配的某个 64 位指针的值完全相同。

【讨论】:

所以我的示例代码会导致 gc 过早删除对象?基本上必须维护明确的指针地址? 如果你的指针数组被 GC 分配并且数组中的指针被 GC 分配,它会找到那些。 我没有指针数组,我有一个指针和一组偏移量。我想我应该说得更清楚。 那么这些可能会被提前释放 但是你是怎么得到指针+偏移量的呢?您需要 GC_ALLOCATE 指针开始,否则它们在 GC 之外。因此,您将不得不 GC_ALLOCATED 一堆指针,然后将这些指针扔掉,但只将可能的负偏移量存储到任意其他指针。

以上是关于C++ 垃圾回收的主要内容,如果未能解决你的问题,请参考以下文章

从C和C++内存管理来谈谈JVM的垃圾回收算法设计-下

Unity优化如何写一个C++垃圾回收器!

JVM专题--垃圾回收算法, 垃圾回收器

从C和C++内存管理来谈谈JVM的垃圾回收算法设计-上

从C和C++内存管理来谈谈JVM的垃圾回收算法设计-上

JVM的垃圾回收机制 总结(垃圾收集回收算法垃圾回收器)