Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby forcing garbage collection not working 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 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?

like image 243
aoiee Avatar asked Jun 12 '26 20:06

aoiee


1 Answers

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
like image 167
Simple Lime Avatar answered Jun 17 '26 08:06

Simple Lime



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!