I’ve found a weird effect when trying to track down a memory leak in a Rails app. Can anyone explain what’s going on here?
Save this script as a plain Ruby script (Rails not necessary):
class Fnord
def to_s
'fnord'
end
end
def test
f = Fnord.new
end
test
GC.start
sleep 2
ObjectSpace.each_object do |o|
puts o if o.is_a? Fnord
end
When I run this via
ruby 1.8.7 (2009-06-12 patchlevel 174) [i486-linux]
I get the following:
bash $ ruby var_test
fnord
Although the variable f is out of scope, there are no other references to the single Fnord object, and I’ve garbage collected, the object still seems to exist. Is this a nefarious memory leak of some sort, or am I completely missing something about Ruby?
Further, if I change the test method to this:
def test
f = Fnord.new
f = nil
end
I get no output. But surely this should not change the semantics here?
Many thanks!
I think the difference between your two versions is not about the value of f, but about the fact that in your first version
testwill return the new Fnord object while in the second versiontestwill returnnil.As a matter of fact the object will be garbage collected if any value comes between
Fnord.newandGC.start. For example simply adding a line42between the call totestand the call toGC.startwill cause the object to be collected.I’m not sure why this is the case, but I suspect that the ruby interpreter holds on to the value of the last evaluated expression for some reason.