"Eustaquio Rangel de Oliveira Jr." <eustaquiorangel / yahoo.com> writes:

> My question is, when assigning nil to c1, it should not invalidate all
> the inner objects and becomes available for garbage collection?
> On the example above, I assigned nil to c1 and c4.next (5), and after
> the GC.start I don't have 5, but still have c1 (same id), 2 and 3. On
> that case, that memory will never be sweeped (free)? Because seems
> that I'll always have a Object with id -604874856 and will not have a
> way to refer to it later, for use or free the allocated memory for it.

Ruby's GC is lazy and conservative. Lazy meaning, it does not
exhaustively try to do path-finding on each object because for some
objects, path-finding is an expensive process. Conservative meaning,
if it is not doing a path-finding on an object, that object is not
freed.

Hate it or love it. It has both advantages and disadvantages. You have
just shown a disadvantage. But it can be mitigated by exiting the
scope which should make path-finding to those objects cheaper.



class CustomObject
  attr_accessor :val, :next
  def initialize(v,n=nil)
    @val        = v
    @next       = n
  end
  def to_s
    "Object #{@val} (#{self.object_id}) points to #{@next.nil? ? 'nothing' : @next.val} (#{@next.nil? ? '':@next.object_id})"
  end
end

def list
  print "Listing all CustomObject's with ObjectSpace\n"
  print "#{ObjectSpace.each_object(CustomObject) {|v| puts v}} objects found\n\n"
end

begin                           # start a new scope so we can exit it later
  c1 = CustomObject.new(1,CustomObject.new(2,CustomObject.new(3)))
  c4 = CustomObject.new(4,CustomObject.new(5))
  c6 = CustomObject.new(6)
  c1.next.next.next = c1        # comment this and check again
  puts "### Initial"
  list
  
  c1 = nil
  c4.next = nil

  GC.start

  puts "### After gc, but still within declaring scope"
  list
end

puts "### Exitted the scope"
list

GC.start                        # here I want c1 disappears

puts "### After gc, outside of declaring scope"
list




Output:

### Initial
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to 5 (-604561922)
Object 5 (-604561922) points to nothing ()
Object 1 (-604561912) points to 2 (-604561902)
Object 2 (-604561902) points to 3 (-604561892)
Object 3 (-604561892) points to 1 (-604561912)
6 objects found

### After gc, but still within declaring scope
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to nothing ()
Object 1 (-604561912) points to 2 (-604561902)
Object 2 (-604561902) points to 3 (-604561892)
Object 3 (-604561892) points to 1 (-604561912)
5 objects found

### Exitted the scope
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to nothing ()
Object 1 (-604561912) points to 2 (-604561902)
Object 2 (-604561902) points to 3 (-604561892)
Object 3 (-604561892) points to 1 (-604561912)
5 objects found

### After gc, outside of declaring scope
Listing all CustomObject's with ObjectSpace
Object 6 (-604561942) points to nothing ()
Object 4 (-604561932) points to nothing ()
2 objects found