在尝试跟踪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
我没有输出。但是这肯定不会改变这里的语义吗?
非常感谢!
答案 0 :(得分:2)
我认为您的两个版本之间的区别不在于f的值,而在于您的第一个版本test
将在第二个版本test
中返回新的Fnord对象这一事实返回nil
。
事实上,如果Fnord.new
和GC.start
之间存在任何值,则会对对象进行垃圾回收。例如,只需在调用42
和调用test
之间添加一行GC.start
即可收集该对象。
我不确定为什么会这样,但我怀疑ruby解释器出于某种原因保留了最后一个评估表达式的值。