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"