From: Tim Pease Date: 2008-01-11T05:25:41+09:00 Subject: Re: why does this code leak? On Jan 10, 2008, at 1:03 PM, Rick DeNatale wrote: > Right, this analysis is correct for Robert's code, and I was thinking > the same thing about Ara's "leaky_finalizer" code as well, but that > code, here simplified, doesn't have the same problem as far as I can > tell: > > class Class > > > def leaky_finalizer > lambda{} > end > > def new *a, &b > object = allocate > object.send :initialize, *a, &b > object > ensure > ObjectSpace.define_finalizer object, leaky_finalizer > end > end > > end > > Note that we are in class Class so self when the lambda is created is > not the new instance but Class itself. In this case it looks as if > the lambda (or something else) is holding on to the binding of the > caller of the finalize method where object is bound to the object to > be finalized. > Hmmm ... I get the same results as my previous example: $ cat a.rb class Class def leaky_finalizer lambda {|object_id| puts "#{object_id} #{local_variables.inspect} #{instance_variables.inspect}" } end def new(*a, &b) object = allocate object.send :initialize, *a, &b object ensure ObjectSpace.define_finalizer object, leaky_finalizer end end class Foo; end 10.times { GC.start Foo.new p "Foo" => ObjectSpace.each_object(Foo){} } $ ruby a.rb {"Foo"=>1} {"Foo"=>2} {"Foo"=>3} 84800 ["object_id"] [] {"Foo"=>3} 89480 ["object_id"] [] 84470 ["object_id"] [] {"Foo"=>2} {"Foo"=>3} 84360 ["object_id"] [] 83880 ["object_id"] [] {"Foo"=>2} 89480 ["object_id"] [] {"Foo"=>2} 83740 ["object_id"] [] {"Foo"=>2} 84730 ["object_id"] [] {"Foo"=>2} 84770 ["object_id"] [] 84800 ["object_id"] [] It looks like everything is getting cleaned up -- just not as quickly as one would assume. But by the end of the program, all 10 finalizers have been called. Blessings, TwP