Локальные переменные и стек - PullRequest
3 голосов
/ 17 декабря 2010

Что будет в следующем фрагменте кода:

while (!Done)
{
     Data data = source.GetData();
     sink.ProcessData(data);
}

Новая ссылка data помещается в стек на каждой итерации цикла (что предотвращает сборку мусора для объекта data ссылок), или ссылка повторно используется в каждой итерации?

Ответы [ 8 ]

8 голосов
/ 17 декабря 2010

Новые эталонные данные помещаются в стек на каждой итерации цикла (что предотвращает сбор мусора ссылок на данные объекта), или эта ссылка повторно используется в каждой итерации?

IПодумайте, на ваш «главный» вопрос о повторном использовании получен адекватный ответ, но скобки крайне важны. Ваше предположение, что это предотвращает сборку мусора, неверно .Если сборщик мусора обнаруживает, что единственной ссылкой на «данные» является слот стека и что никто больше никогда не будет читать из него , тогда сборщику мусора будет разрешено восстановить хранилище даже приссылка на стек .Это может быть плохо, если объект, потребляющий слот стека, является неуправляемым кодом, о котором GC не знает.

Если вам нужно что-то сохранить, удерживая его в стеке, тогда вам нужнодобавить KeepAlive к методу .

2 голосов
/ 17 декабря 2010

Как вы говорите, переменная «используется повторно». Переменные стека / локальные - это всего лишь локальные для метода, а не для области видимости. Область, в которой находится ваша переменная data, только не позволяет увидеть ее вне этой области, и наоборот, НЕ определяет переменную ячейку стека.

Джон Скит хорошо говорит , как всегда.

1 голос
/ 17 декабря 2010

Ничего не происходит, так как компилятор оптимизировал бы его примерно так, как показано ниже при выпуске релиза:

sink.ProcessData(source.GetData());

Если вы создаете переменные и разыменовываете их быстрее, происходит фрагментация heap, поэтому у нас есть циклические буферы.

1 голос
/ 17 декабря 2010

Учтите это:

    private class test
    {
        ~test()
        {
        }
    }

    static void Main()
    {
        while (true)
        {
            GC.Collect();
            test t = new test();
        }
    }

т повторно используется в каждом цикле. Но если вы установите точку останова в финализаторе тестового класса, она будет достигнута после переназначения третьей переменной времени t.

1 голос
/ 17 декабря 2010

Данные, если это ссылочный тип , всегда идут в кучу.Если это ValueType, то здесь идет стек.

Сама ссылка будет использоваться повторно.

1 голос
/ 17 декабря 2010

Переменные внутри цикла не сохраняются в течение итераций, поэтому они эффективно сбрасываются в каждом цикле - то, что компилятор делает с ними под капотом, это его дело:)

Если это ссылка, указатель сбрасывается, и объект становится ответственным за сборщик мусора, если вы не подключите его где-то еще.

1 голос
/ 17 декабря 2010

Ссылка помещается в стек (сама переменная выделяется в куче) и не будет повторно использоваться в каждой итерации.Вместо этого он становится недоступным после завершения цикла while и становится пригодным для сбора мусора (если только вы не храните его где-то внутри приемника).

0 голосов
/ 17 декабря 2010

Я считаю, что каждый раз это новый экземпляр. Почему это предотвратит сборку мусора?

...