问题
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