Почему мой объект Ruby не удаляется, когда последняя ссылка выходит из области видимости? - PullRequest
2 голосов
/ 04 апреля 2010

Я обнаружил странный эффект при попытке отследить утечку памяти в приложении 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

Я не получаю вывод. Но, конечно, это не должно изменить семантику здесь?

Большое спасибо!

1 Ответ

2 голосов
/ 04 апреля 2010

Я думаю, что разница между вашими двумя версиями не в значении f, а в том, что в вашей первой версии test вернет новый объект Fnord, а во второй версии test вернет nil .

На самом деле объект будет собираться мусором, если любое значение находится между Fnord.new и GC.start. Например, простое добавление строки 42 между вызовом test и вызовом GC.start приведет к тому, что объект будет собран.

Я не уверен, почему это так, но я подозреваю, что интерпретатор ruby ​​по какой-то причине сохраняет значение последнего вычисленного выражения.

...