我发现了一个奇怪的效果,当我试图追踪一个rails应用程序的内存泄漏。有人能解释这是怎么回事吗?
将此脚本另存为纯ruby脚本(不需要rails):
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
当我通过
ruby 1.8.7 (2009-06-12 patchlevel 174) [i486-linux]
我得到以下信息:
bash $ ruby var_test
fnord
虽然变量F超出了范围,但是没有其他引用到单个FNORD对象,并且我已经收集了垃圾,对象似乎仍然存在。这是某种邪恶的内存泄漏,还是我完全忽略了ruby?
此外,如果我将测试方法改为:
def test
f = Fnord.new
f = nil
end
我没有输出。但这肯定不会改变这里的语义吗?
非常感谢!
最佳答案
我认为两个版本之间的区别不在于f的值,而在于第一个版本中test
将返回新的fnord对象,而第二个版本中test
将返回nil
。
事实上,如果任何值介于Fnord.new
和GC.start
之间,对象将被垃圾收集例如,只需在对42
的调用和对test
的调用之间添加一行GC.start
将导致收集对象。
我不知道为什么会这样,但我怀疑ruby解释器出于某种原因保留了最后一个计算表达式的值。