2017-07-18 51 views
2

在下面的代碼不工作:紅寶石迫使垃圾收集預期

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

+0

我看到'dead'打印,如果我使用控制關閉您的代碼+ C,以及如果我取代'exit'了'而真正end'作爲。我在Ruby 2.5.0-dev fwiw上。你在哪個平臺上? –

+0

我在eclipse上使用Ruby 2.4.0 – aoiee

+0

哦,並且沒有GC.start的終結器工作? –

回答

1

我相信,當你創建一個新的Procproc只是調用Proc.new,在Kernel

創建一個新的進程內對象綁定到當前上下文。

意味着它保存對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 
+0

非常感謝您的解釋!我試過了,它甚至沒有額外的'puts'對象id =#{ex.object_id}「'。 – aoiee

+1

啊,是的,我不記得以前需要它,但沒有它我沒有運行,所以在我的ruby實現中,我猜,但我的意思是,在實際的例子中,你可能使用的對象的東西無論如何,不​​只是實例化事物,以便我們可以運行終結器。 –