我发现了一个奇怪的效果,当我试图追踪一个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.newGC.start之间,对象将被垃圾收集例如,只需在对42的调用和对test的调用之间添加一行GC.start将导致收集对象。
我不知道为什么会这样,但我怀疑ruby解释器出于某种原因保留了最后一个计算表达式的值。

09-28 04:01