11

Смотрите также эти ресурсы:Может ли соответствующий C# компилятор оптимизировать локальную (но неиспользуемую) переменную, если она является единственной сильной ссылкой на объект?


Другими словами:

Может ли объект на который ссылается локальной переменной быть утилизирован, прежде чем переменная выходит из области видимости (например. , потому что переменная назначена, но не используется снова), или это то, что объект гарантированно недействителен для сбор мусора до тех пор, пока переменная не выходит за рамки?

Поясню:


void Case_1() 
{ 
    var weakRef = new WeakReference(new object()); 

    GC.Collect(); // <-- doesn't have to be an explicit call; just assume that 
        //  garbage collection would occur at this point. 

    if (weakRef.IsAlive) ... 
} 

В этом примере кода, я, безусловно, должны планировать возможность того, что new'ed object будет утилизирован сборщиком мусора; поэтому заявление if.

(Обратите внимание, что я использую weakRef с единственной целью проверки, если new'ed object все еще вокруг.)


void Case_2() 
{ 
    var unusedLocalVar = new object(); 
    var weakRef = new WeakReference(unusedLocalVar); 

    GC.Collect(); // <-- doesn't have to be an explicit call; just assume that 
        //  garbage collection would occur at this point. 

    Debug.Assert(weakRef.IsAlive); 
} 

Основное изменение в этом примере кода из предыдущего заключается в том, что в new'ed object строго указана локальная переменная (unusedLocalVar). Однако эта переменная никогда не используется снова после того, как была создана слабая ссылка (weakRef).


Вопрос: ли соответствующий требованиям C# компилятор позволил оптимизировать первые две строки Case_2 в тех Case_1, если он видит, что unusedLocalVar используется только в одном месте, а именно в качестве аргумента в WeakReference конструктора? то есть есть ли вероятность, что утверждение в Case_2 могло бы потерпеть неудачу?

ответ

11

Не имеет значения, что делает компилятор C# - JITTER/GC разрешено очищать локальные ссылки, если они больше не живы в теле метода. Посмотрите на документы для GC.KeepAlive

Кроме того, этот powerpoint presentation, особенно с слайда 30, помогает объяснить, что может сделать JIT/GC.

+4

Также обратите внимание, что в отладочных сборках переменная явно сохраняется до конца области для просмотра отладчиком - только в версиях вы увидите это поведение. –

+0

@ Энди - интересный момент. Не то чтобы это важно, но я предполагаю, что это поведение управляется JITter? –

+4

И для полноты, поэтому установка 'unusedLocalVar = null' в _end_ метода обычно является де-оптимизацией. –

3

Хотя мой вопрос был дан ответ, я думал, что я отправлю эту соответствующую часть информации, которую я только что нашел на блоге статью MSDN "WP7: When does GC Consider a Local Variable as Garbage" по abhinaba:

[T] он ECMA спецификации (ECMA 334 Раздел 10.9) [& hellip;] состояния

«например, если локальная переменная, которая находится в области видимости является единственной существующей ссылкой на объект, но, что локальная переменная никогда не упоминается в любом возможном продолжении исполнения от текущая точка выполнения в процедуре, (но не требуется) обрабатывать объект, поскольку он больше не используется ».

Это все говорит. В упомянутой статье также говорится, что платформа .NET (по крайней мере, в режиме Release) будет выполнять прогностический анализ и освобождать такие объекты, в то время как .NET Compact Framework не будет (по соображениям производительности).

0

Является соответствующий C# компилятор позволил оптимизировать первые две строки Case_2 в тех Case_1, если он видит, что unusedLocalVar используется только в одном месте, а именно в качестве аргумента конструктора WeakReference?

Эти два определения эквивалентны, поэтому переход от одного к другому не является «оптимизацией», потому что ни один из них не является более эффективным.

i.e есть ли вероятность того, что утверждение в Case_2 может провалиться?

Да. Компилятор производства вряд ли сохранит ссылку без необходимости, поэтому он будет удален, GC не увидит его как глобальный корень и соберет этот объект.

Обратите внимание, что сборщики мусора не видят вашу программу с точки зрения переменных и объема. Эти концепции высокого уровня уже давно скомпилированы к тому моменту, когда ваш код попадает в сборщик мусора. GC видит только регистры, стеки потоков и глобальные переменные.