Ruby garbage disposal does not work as expected

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 is never called here and there is no exit. I was expecting the garbage collector to collect ex

as it was dereferenced. Why GC.start

doesn't it force you ex

to collect and summons finalizer to be called

right away?

+3


source to share


1 answer


I believe that when you create a new one Proc

( Proc

just calls Proc.new

, in Kernel

)

Creates a new Proc object bound to the current context.

means it retains a reference to the object self

and therefore can never be reversed for the garbage collector to collect it. You have to create Proc

inside a class method instead so that the context becomes the class and not the instance you are 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 these outputs

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

      

+2


source







All Articles