首页 > 解决方案 > 如何使用 Boehm GC 实现弱引用?

问题描述

我有一个使用 Boehm GC 实现的个人项目。我需要实现一种事件类型,它应该包含对其他事件的引用。但我还需要确保指向的事件仍然是可收集的,因此我需要弱引用。

假设我们有事件 A、B 和 C。我将这些事件配置为在发出任何信号时发出事件 X 的信号。这意味着 A、B 和 C 必须持有对事件 X 的引用。我想要的是,如果事件 X 不可访问,则事件 A、B 和 C 不再需要发出信号。因此,我想到的是弱参考。

有没有其他方法可以做到这一点?我不想更改 GC,但如有必要(分配界面保持干净)我可以。

该项目是用 C 编写的。如果需要,我将提供更多信息。值得注意的是,如果有任何方法可以直接使用这种语义实现此类事件,则不需要实际的弱引用(事件可能有一个引用周期,尽管它们没有发出信号)。

标签: cboehm-gc

解决方案


Boehm GC本身没有弱引用的概念。但是,它不会扫描系统分配的内存malloc以查找对托管对象的引用,因此存储在此类内存中的指针不会阻止收集指向的对象。当然,这种方法意味着包含指针的对象不会由收集器管理。

或者,应该可以滥用GC_MALLOC_ATOMIC()GC_malloc_explicitly_typed()获得一个托管对象,该对象可以包含指向其他托管对象的指针,而不会阻止收集这些其他对象。这基本上涉及向 GC 谎报某些成员是否是指针,以防止它们被扫描。

无论哪种方式,您还需要一些机制来在收集弱引用对象时接收通知,以避免之后尝试访问它们。GC 有一个接口,用于注册要在收集对象之前调用的终结器回调,这看起来是您为此目的最好的选择。

总的来说,我认为您的要求是可行的,但涉及很多 DIY。在高水平上,

  • 用于GC_MALLOC_ATOMIC()围绕指向弱引用对象的指针分配包装对象。以这种方式分配它允许包装器本身由 GC 管理,而不会在 GC 的可达性分析期间扫描指针。
  • 用于GC_register_finalizer注册一个终结器函数,该函数将包装器的指针设置为NULLGC 决定指向的对象不可访问时。
  • 包装器的用户有义务NULL在尝试取消引用之前检查其中的指针是否存在。

推荐阅读