Circular References: How to prove that they are garbage collected

K

Karsten Meier

Hello Ruby Fans

I'm converting a perl example which deals with the circular data
structures, and how to make sure they are destroyed properly.
(For the pleac cookbook, pleac.sourceforge.net)

I have read several times that the garbage collector has no problems
with circular references, so I tried to prove it.
But with my ruby 1.8.0 it looks like the garbage collector
does not destroys the Node A, B and C, but only the lonely node:

GC.enable

class RingNode
attr_accessor :next
attr_accessor :prev
attr_reader :name

def initialize(aName)
@name = aName
ObjectSpace.define_finalizer(self,
self.class.method:)finalize).to_proc)
end

def RingNode.finalize(id)
puts "Node #{id} dying"
end

def RingNode.show_all_objects
ObjectSpace.each_object {|id|
puts id.name if id.class == RingNode
}
end
end

a = RingNode.new("Node A")
b = RingNode.new("Node B")
c = RingNode.new("Node C")
a.next = b
b.next = c
c.next = a
a.prev = c
c.prev = b
b.prev = a
lonely = RingNode.new("Lonely node")

a = nil
b = nil
c = nil
lonely = nil

GC.start
puts "Garbage Collection called"
RingNode.show_all_objects
puts "End of Program"


What happens is that Noda A,B,C get destroyed, but after the end of the
program. If I comment out the finalizer (in case I made an error with
it) and only use the ObjectSpace.each_object, I see also Node A,B,C
after the garbage collection.
 
J

Joel VanderWerf

Karsten said:
Hello Ruby Fans

I'm converting a perl example which deals with the circular data
structures, and how to make sure they are destroyed properly.
(For the pleac cookbook, pleac.sourceforge.net)

I have read several times that the garbage collector has no problems
with circular references, so I tried to prove it.
But with my ruby 1.8.0 it looks like the garbage collector
does not destroys the Node A, B and C, but only the lonely node:

"Only the lonely
Node the way I feel tonight"

... hehe. Sorry Roy Orbison.

Anyway, try it with the following 3 additional lines. All four nodes
print their message before the "Garbage colection called" message. I
think what's going on is conservatism. Keeping the local vars in a
method makes sure that stack frame is gone begore the GC starts.
 
F

Florian Gross

Moin!

The problems is with the finalizer. It holds a reference to the object
AFAIK.

Maybe you could just capture the .object_id and use ObjectSpace._id2ref
to check whether the Objects still exist after you ran the GC?

Oh, or you could use a WeakRef.

Regards,
Florian Gross
 
J

Joel VanderWerf

Oops... I put the end in the wrong place. It should be like this:

def main
a = RingNode.new("Node A")
b = RingNode.new("Node B")
c = RingNode.new("Node C")
a.next = b
b.next = c
c.next = a
a.prev = c
c.prev = b
b.prev = a
lonely = RingNode.new("Lonely node")

a = nil
b = nil
c = nil
lonely = nil
end

main
GC.start
...
 
K

Karsten Meier

Thanks, this is doing the trick.
Even when I put the assignments to nil also in the function
(just to be sure that there is has nothing to do with C++ style
destruction of objects on the stack when leaving the function)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top