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”