From: Garthy D Date: 2011-11-29T21:43:15+09:00 Subject: Garbage collection and define_finalizer Hi. I was wondering if running the (mark and sweep?) garbage collector manually is supposed to collect (and call define_finalizer procs on) objects with no remaining references. I would expect that the answer is yes, but it doesn't seem to actually work that way. When I run the script below (based on some examples online that apparently avoid some of the problems with define_finalizer), the output suggests that the finalizer for an allocated and unused object of class A isn't actually being called until *after* the garbage collection is complete and the program has reached the end. This suggests that calling the garbage collector doesn't actually cause unreferenced objects to be reaped immediately. Is there a fault in my assumptions or the script below? If you wrap the A.new in a loop instead, eventually it'll free up the other instances of A en-masse (ie. calling the GC doesn't seem to do it, but flooding memory until the GC triggers does). I have seen similar behavior in a large embedded Ruby program that I am working on. In this case the Ruby objects in question have instance variables that reference textures, and I really need the finalizer to be called when all of the references to the textures are lost, so as to free up the texture memory. At the moment they are being finalised at program exit, when the available texture memory has long run out. This isn't good, and it means I need to rewrite every potential bit of this code to use manual reference counting. So basically: If the garbage collector is called, are objects with no remaining references supposed to be reaped during the call, and their defined finalizers called? Whatever the answer- why is that? Is there an official word on how this is supposed to work, and what can (and can't) be relied upon? Any thoughts? Cheers, Garthy --- #!/usr/bin/ruby -w ###!/packages/ruby/bin/ruby -w class A def initialize ObjectSpace.define_finalizer(self, self.class.method(:finalize).to_proc) #ObjectSpace.define_finalizer(self, self.class.finalize2) @a = 1 $stderr.print "Init A\n" end def self.finalize(id) $stderr.print "Finalise called for: #{id}.\n" end def self.finalize2 proc {$stderr.print "Finalise called.\n"} end end def do_gc GC.start #ObjectSpace.garbage_collect end def foo a = A.new nil end foo $stderr.print "Starting garbage collection.\n" do_gc $stderr.print "Finished garbage collection.\n"