【问题标题】:Does calling `gc()` manually, result in all `finalizers` being executed immediately?手动调用`gc()`会导致所有`finalizers`立即执行吗?
【发布时间】:2017-06-10 02:57:05
【问题描述】:

我有一些我怀疑是内存泄漏的代码。 由于代码使用ccall 并维护指针内保存的重要信息, 在finalizers 期间应该通过ccalled 的代码释放它们。

在我的调试中,我打电话给gc()。 而且我想知道这是否会立即触发所有附加到已移出范围的对象的finalizers

答案应该只关注 julie 0.5+。

【问题讨论】:

    标签: garbage-collection julia finalization


    【解决方案1】:

    在讨论了@Isaiah 的答案(已删除)之后,我决定戳戳一些内部人员并弄清楚这一点。因此,我有充分的权威表明,当gc()在顶级调用(即不在本地范围内)时,可以依赖以下保证:

    如果一个对象无法访问并且您调用gc(),它将被最终确定

    这是非常明确的。顶级部分很重要,因为当您在本地范围内调用 gc() 时,本地引用可能被认为是可访问的,也可能不被认为是可访问的,即使它们永远不会被再次使用。

    这种保证确实在“可达性”的地毯下扫除了一些不确定性,因为对象是否可达可能并不明显,因为语言运行时可能会出于各种原因保留对某些对象的引用。这些原因应该详尽地记录下来,但目前还没有。运行时保留对象的几个值得注意的情况是:

    • 单例类型的唯一实例是永久的,永远不会被收集或终结;

    • 方法缓存也是永久性的,这尤其意味着当您可能期望它们被释放时,模块不会被释放,因为方法缓存会保留对定义它们的模块的引用。

      李>

    然而,在“正常情况下”——这就是我怀疑这个问题的意思——是的,当一个对象不再可访问时调用 gc()导致它被收集并最终确定“立即”,即在gc() 调用返回之前。

    【讨论】:

    • 斯特凡回答得很好。公平地说,这仅适用于当前的 gc() 实现,而不是语言合同吗?即,这种行为将来可能会改变。例如,如果我们得到一个多线程 gc?
    • 是的,如果我们得到一个并发的 gc,所有的赌注都被取消了——但我们当然必须考虑它的影响。在并发 gc 中,有同时运行的 mutator 线程和收集器线程,因此在 mutator 线程中调用 gc() 甚至意味着什么并不完全清楚。它可能会被安排阻塞调用它的 mutator 线程,直到收集器线程中发生“完整收集”。或者它可以调用一个 stop-the-world gc 算法来代替并发收集器,但是我们有两个不同的 gc 实现,这很奇怪。
    猜你喜欢
    • 2012-05-24
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 2020-11-04
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    相关资源
    最近更新 更多