2015-10-29 3 views
2

рассмотрите следующие утвержденияЧто происходит с объектом после GC?

void foo() 
{ 
    string text = "something"; 
    int a = 10; 
    int b = a; 

    var array = new int[5]{2,1,3,5,4}; 

    GC.Collect(); 
} 



**Stack**   **Heap** 

text = 0x20   0x20 something 

a = 10 

b = 10 

array = 0x50:0x55 0x50 2 
        0x52 1 
        0x53 3 
        0x54 5 
        0x55 4 

Некоторые предположения:

  1. GC.Collect() вызывается в конце метода.
  2. GC работает (предположим).

Вопросы были:

  1. Что такое значение в Heap?

    Я ответил на ячейки памяти 0x20, 0x50-0x55 будет исправлен и удален. Снова он спросил, какие значения имеют места памяти? Я предположил, что это мусорные ценности. Он сказал неправильно. (WTx?)

  2. Что происходит с элементами в стеке? Какие значения имеет значение для массива text, a, b?

    Я ответил, что поскольку ссылки, которые они содержат, уже удалены, и они также будут исправлены. Он спросил, какие значения теперь сохраняют переменные.

  3. Переверните приведенную выше табличную колонку после GC Collection.

    После GC работает

    **Stack**   **Heap** 
    
    text (cleared)  0x20 Garbage/NULL 
    
    a (cleared) 
    
    b (cleared) 
    
    array (cleared)  0x50 Garbage/NULL 
            0x52 Garbage/NULL 
            0x53 Garbage/NULL 
            0x54 Garbage/NULL 
            0x55 Garbage/NULL 
    

Результат: Он сказал, что ответы были неправильными. Любые идеи, чего я здесь не хватает?

+0

Почему существует запрос «закрыть»? Я просто пытаюсь найти ответы на неизвестные. Любые документы/мысли/ответы/ссылки приветствуются –

ответ

5

Невозможно дать на это детерминированный ответ, но некоторые могут подумать о поведении.

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

Однако, для всех целей и задач эти переменные больше не существуют после метод вернулся.

Если вы думаете, что «эти переменные живут в стеке», please note that the stack is an implementation detail.

Теперь дополнительно выделены два объекта кучи, строка и массив.

Поскольку эти ссылки ссылались только на локальные переменные, выходящие за рамки после возврата метода, они больше не считаются живыми и имеют право на сбор.

Однако, что означает «коллекция»? Означает ли это, что сборщик мусора очищает область памяти? Не за что.

Вместо этого, когда мусор собирает память, он фактически делает обратное, это collects living objects. Эти объекты уплотняются в памяти и перемещаются, а область, в которой эта строка и этот массив может быть перезаписана другими объектами. Может быть массив, содержащий только нули, и в этом случае область памяти, скорее всего, будет выглядеть «очищенной», но, вероятно, нет.

Но держитесь, эта строка, с ней что-то особенное. Поскольку строка была написана в исходном коде как литерал, на самом деле это interned при запуске программы. Таким образом, не собрано, это будет еще жить где-то в памяти. Другими словами, эта строка все еще жива и хорошо, где-то в памяти. Может быть, это то же самое место, в котором была упомянутая переменная, может быть где-то в другом месте. Мы не можем знать.

Байты, составляющие объект массива, однако, могут быть перезаписаны сборщиком мусора, когда он уплотняет живые объекты.

OK, поэтому все это бывает после способ возвращен.

Что произойдет, если GC.Collect() запускает цикл сбора мусора до метод возвращается?

Хорошо, если вы находитесь в сборке RELEASE, все вышеперечисленное остается. Тот факт, что у вас есть локальная переменная в методе, ссылающемся на что-то в куче, ничего не значит, если переменная больше не используется в методе (т. Е. Вы передали последнее использование на временной шкале выполнения).

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

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


Здесь приходит фактический ответ на ваш вопрос:

Многое из выше деталей реализации. Мы не должны заботиться о них, потому что это может измениться из-за оптимизации.

Есть много вещей, о которых мы можем рассуждать, но о том, как обрабатывать фактическую базовую память, мы не должны.

Вы сказали в своем комментарии, что считаете, что находитесь в интервью писателя-компилятора, и я бы сказал, что чувство правильное. Если бы вы взяли интервью для группы управления JIT или управления памятью в Microsoft, некоторые знания о том, как это работает, будут, по крайней мере, преподаваться как часть работы, но могут быть бонусом, если вы уже знаете.

Однако для обычного .NET-программиста это необязательно заботиться. Другие умные люди заботятся об этом.

1

Это то, на что вы не можете ответить, потому что это деталь реализации вашей платформы исполнения. В зависимости от платформы/версии ответ может быть совершенно другим. То, что вы можете рассмотреть, - это область метода, тип значения vs reference type и специальные строки.

+0

Мои мысли точно! Я не знаю, чего еще требовал интервьюер. ** Просто хотел подтвердить, как вторая мысль: «Мой рисунок стека и кучи правилен после GC Collection? ** –

+1

Нет, это определенно неверно. GC не будет ничего делать в стеке. И строка никогда не будет очищена, потому что она обычно реализуется как const. – Peter

+0

Uh Oh! Итак, любые идеи, которые очищают стек? Под словом «исправлено» или «очищено», что происходит с местом памяти? Установлено сброшенное значение или значение по умолчанию или значение null. Я смущен –

2

Один из трех возможных вещей может произойти в памяти ранее занимаемого объекта:

  • Он переписывается другим объектом. Тот, который был перемещен, когда GC сжал кучу. Это наиболее вероятный результат.
  • Он добавляется в свободный список сегмента кучи, готовый для использования при следующем распределении. Обычно после слияния с свободным пространством или выделениями до и после блока, если они были выпущены, это обычное явление.
  • Это было последнее оставшееся распределение в сегменте кучи. Сегмент может быть добавлен в пул неиспользуемых сегментов, он будет использоваться повторно, если нужен новый сегмент # 0. Или адресное пространство для него может быть возвращено операционной системе.

Куча больших предметов немного отличается, первая пуля не применяется. Обратите внимание, что ментальная модель «места памяти удалена» не очень точна. Вы будете намного опережать «места памяти будут повторно использоваться». То же самое касается стека, нет активного кода «удалить код стека». Он просто забывается и рано или поздно будет перезаписан. Почти всегда раньше, микросекунды.

Смежные вопросы