2

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

出力がありません。しかし、確かにこれはここでのセマンティクスを変更するべきではありませんか?

どうもありがとう!

4

1 に答える 1

2

2つのバージョンの違いは、fの値ではなく、最初のバージョンでtestは新しいFnordオブジェクトを返し、2番目のバージョンでは。testを返すという事実についてだと思いますnil

実際のところ、との間Fnord.newに値が入ると、オブジェクトはガベージコレクションされGC.startます。たとえば、toの呼び出しとtoの呼び出しの間に行を追加するだけで42、オブジェクトが収集されます。testGC.start

なぜそうなるのかはわかりませんが、ルビーインタプリタが何らかの理由で最後に評価された式の値を保持しているのではないかと思います。

于 2010-04-04T19:12:12.623 に答える