【问题标题】:Why isn't my Ruby object deleted when the last reference goes out of scope?当最后一个引用超出范围时,为什么我的 Ruby 对象没有被删除?
【发布时间】:2010-04-04 19:06:22
【问题描述】:

我在尝试跟踪 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

我没有输出。但这肯定不应该改变这里的语义吗?

非常感谢!

【问题讨论】:

    标签: ruby memory-leaks scoping


    【解决方案1】:

    我认为你的两个版本之间的区别不在于 f 的值,而在于你的第一个版本中 test 将返回新的 Fnord 对象,而在第二个版本中 test 将返回 nil .

    事实上,如果有任何值介于Fnord.newGC.start 之间,则该对象将被垃圾回收。例如,只需在对 test 的调用和对 GC.start 的调用之间添加一行 42 就会导致对象被收集。

    我不确定为什么会这样,但我怀疑 ruby​​ 解释器出于某种原因保留了最后一个评估表达式的值。

    【讨论】:

    • 是的,最后一个表达式的值总是被_ 变量引用。
    • @Chuck:不过,只有在 irb 中。如果我将23+19 然后puts _ 放入rb 文件并运行它,我会得到“未定义的局部变量或方法`_' for main:Object (NameError)”。
    猜你喜欢
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 2020-09-04
    • 2022-11-30
    • 2012-04-22
    • 1970-01-01
    相关资源
    最近更新 更多