>>>>> "W" == Wincent Colaiuta <win / wincent.com> writes: W> def parse W> # do stuff W> cache = MemoizingCache.new ^^^^^ W> $stderr.print "New cache id #{cache.object_id}\n" W> ObjectSpace.define_finalizer(cache, lambda { |id| $stderr.print ^^^^^^ W> "Finalizer for id #{id}\n"}) W> # do more stuff W> end W> And have confirmed that the cache finalizers are not being called. I W> haven't found out how the reference to the local "cache" variable is W> being kept alive even after it falls out of scope, but you've given me W> the tool necessary to at least find out what's happening. The closure (lambda) has a reference to the variable cache Here a stupid example moulon% cat b.rb #!/usr/bin/ruby class A def parse cache = Array.new(100) ObjectSpace.define_finalizer(cache, lambda {|i| $stderr.puts "obj_id #{i}" }) end end ARGV[0].to_i.times { A.new.parse } $stderr.puts "gc" GC.start $stderr.puts "at end" moulon% moulon% ./b.rb 2 gc at end obj_id -605590758 obj_id -605590688 moulon% Now if I change this to moulon% cat b.rb #!/usr/bin/ruby class A def self.x lambda {|i| $stderr.puts "obj_id #{i}" } end def parse cache = Array.new(100) ObjectSpace.define_finalizer(cache, A.x) end end ARGV[0].to_i.times { A.new.parse } $stderr.puts "gc" GC.start $stderr.puts "at end" moulon% moulon% ./b.rb 2 gc obj_id -605498718 at end obj_id -605498798 moulon% only one object is freed when GC.start run and you can see it with this case moulon% ./b.rb 1 gc at end obj_id -605640028 moulon% ruby call the finalizer at the end only, because when GC.start run it find a reference to the object (in cache) on the stack and mark it Guy Decoux