【问题标题】:How does one implement weak references with Boehm GC?如何使用 Boehm GC 实现弱引用?
【发布时间】:2019-05-01 13:35:15
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: c boehm-gc


    【解决方案1】:

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

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

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

    总体而言,我认为您的要求是可行的,但涉及很多 DIY。在高层次上,

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

    【讨论】:

    • 所以基本上我应该制作一种句柄对象,将实际引用存储到收集器不查看的区域中,注册终结器(我如何获取句柄对象而不是实际正在完成的对象?)并在收集该对象时使用它来清零指针?
    • 另外,GC_register_disappearing_link 对我有用吗?
    • 不,我认为GC_register_disappearing_link 不会对您有用。当 包含它的对象 被发现不可访问时,它会导致指针被清零,但是当 它们指向的对象 变得不可访问时,您想清除指针,哪个只要 GC 知道的指针指向该对象,当然就不会发生。
    • 显然 GC_register_finalizer 需要一个指向我的句柄对象的指针,这样就完成了。然后简单地我应该使用 GC_MALLOC_ATOMIC 分配句柄对象的内容,设置为零(我认为 BOEHM 是为我做的),注册一个终结器,当对象本身被收集时清零,然后设置处理程序对象的内容.. . 我认为这可能是一个答案。
    • 好的,@PaulStelian,我已经用建议方法的高级大纲更新了答案。
    猜你喜欢
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多