【问题标题】:Ruby forcing garbage collection not working as expectedRuby 强制垃圾收集无法按预期工作
【发布时间】:2017-07-18 19:24:53
【问题描述】:

在以下代码中:

class ExampleClass
  def initialize
    ObjectSpace.define_finalizer(self, proc{puts 'dead'})
  end
end

ex = ExampleClass.new
ex = nil

GC.start

while true
  # the while loop is to prevent the program from terminate
  # if the program does terminate, the finalizer gets called in the end like expected
end

这里的终结器永远不会被调用,也没有输出。我本来希望垃圾收集器收集ex,因为它已被取消引用。为什么GC.start 不强制收集ex 并立即导致finalizer to be called

【问题讨论】:

  • 如果我使用 control+c 关闭您的代码以及将 while true end 替换为 exit,我会看到 dead 打印。我在 Ruby 2.5.0-dev fwiw 上。你在哪个平台上?
  • 我在 Eclipse 上使用 Ruby 2.4.0
  • 哦,终结器在没有 GC.start 的情况下可以工作吗?
  • 我想知道为什么当我调用GC.startdead 不能正确打印。我在那里放了一个while循环来表明程序没有终止。

标签: ruby garbage-collection finalizer


【解决方案1】:

我相信当你创建一个新的Procproc 只是调用Proc.new,在Kernel

创建一个新的 Proc 对象,绑定到当前上下文。

意味着它正在保存对self 对象的引用,因此永远不能取消引用以供垃圾收集器收集它。您应该在类方法中创建proc,以便上下文成为类而不是您要销毁的实例。

class ExampleClass
  def initialize
    ObjectSpace.define_finalizer(self, self.class.finalize)
  end

  def self.finalize
    proc { puts "dead" }
  end

end


ex = ExampleClass.new
# needed to do something with the object as well, not sure why,
# but it won't work without this line either
puts "object id = #{ex.object_id}"
ex = nil

GC.start
while true
end

这个输出

object id = 70223915005060
dead
^Cexample.rb:20:in `<main>': Interrupt

【讨论】:

  • 非常感谢您的解释!我试过了,它甚至可以在没有额外的 puts "object id = #{ex.object_id}" 的情况下工作。
  • 啊,是的,我不记得以前需要它,但如果没有它,我就无法运行它,所以我想在我的 ruby​​ 实现中有些东西,但我的意思是,在实际示例中你无论如何,可能会将该对象用于某些事情,而不仅仅是实例化事物以便我们可以运行终结器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-17
  • 2015-02-12
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-30
相关资源
最近更新 更多