Ruby forcing garbage collection not working as expected

空扰寡人 提交于 2021-02-08 01:42:09

问题


In the following code:

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

The finalizer here is never called and there is no output. I would have expected the garbage collector to collect ex since it has been dereferenced. Why is GC.start not forcing ex to be collected and causing the finalizer to be called immediately?


回答1:


I believe that when you create a new Proc (proc just calls Proc.new, in Kernel)

Creates a new Proc object, bound to the current context.

Means that it's saving a reference to the self object and thus can never be de-referenced for the garbage collector to collect it. You should create the proc inside a class method instead so that the context becomes the class not the instance you're trying to destroy.

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

and this outputs

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


来源:https://stackoverflow.com/questions/45175422/ruby-forcing-garbage-collection-not-working-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!