标记(在标记和扫描中)函数如何从根部访问的对象集

how does the mark (in mark-and-sweep) function trace out the set of objects accessible from the roots?

本文关键字:根部 访问 对象 函数 扫描 标记      更新时间:2023-10-16

我正在尝试了解商标和扫描算法在一段代码中的工作方式。

我明白,每次我malloc()时,我的malloc()函数会将内存地址添加到链接列表中?然后,当我想垃圾收集时,我调用Mark()函数,该函数在" root"对象中添加,然后从那里标记所有可触及的内存地址。然后,我调用Sweep(),并释放所有未标记的内存地址。

我对"根"对象是什么以及标记函数如何从" root"对象达到的对象感到困惑。

我认为,如果某人能够给我一个小例子,说明我如何用代码来工作...我找不到。

谢谢。

通常有一个root set ,而不仅仅是一个根对象。根集基本上是所有全局变量,并且所有当前活动的本地变量(例如,当前堆栈上的所有当地人)。将垃圾收集添加到C或C 的真正困难之一是可能无法检测到根集中的指针(例如,如果您将指针写入临时文件,则垃圾收集器不知道要寻找的是它)。

弄清楚从那里可以到达的内容意味着对指针进行检查,并指出的指向是可以触及的。如果指向的内容包含一个或多个指针,它将递归地遵循这些指针,因此可以从中可以达到的所有物品也被认为可以达到。

带有"精确"垃圾收集器,您可以使用某种类型的信息来告诉垃圾收集器什么是指示器。例如,每个对象都可能包含一个类型标签,以判断它是什么样的对象。然后,您有一张表可告诉GC(如果在任何地方)该类型的对象是指指针的位置。

使用"保守的"垃圾收集器,您只需查看数据的内容,并假设如果某物可以是指针,那就是指针。您关心的唯一指针是垃圾收集的堆。为了讨论,让我们假设一个64位指针和8兆字节的GC堆。这意味着我们浏览内存,并找到可能是指向GC堆的约800万个值中的任何一个,并假设任何此类值 is 是指针,因此在该地址中的任何内容堆被认为可以到达(如果是的话,我们在其中寻找可能是指针的任何东西,递归)。

尽管最初(对许多人来说)听起来很像后者通常会将所有内容都视为可触及的,但实际上它在真实使用方面确实可以很好地奏效。但是,它确实禁止某些垃圾收集策略。特别是,任何涉及压实堆的事物意味着在对象被移动时需要调整所有对象的指针 - 要执行此操作,我们可以确定我们正在修改的实际修改是指向该对象的指针,而不仅仅是一些整数(或字符串等),它们恰好具有看起来像指针的值。