Известно, что сборщик мусора .NET не просто «удаляет» объекты в куче, но также борется с фрагментацией памяти, используя уплотнение памяти. Насколько я понимаю, в основном память копируется на новое место, а старое место в какой-то момент удаляется.Как среда выполнения .NET перемещает память?
Мой вопрос: как это работает?
Что мне больше всего любопытно, так это то, что GC работает в отдельном потоке, что означает, что объект, над которым мы работаем, может быть перемещен GC , пока мы выполняем наш код.
Технические детали вопроса
Для иллюстрации, позвольте мне объяснить, на мой вопрос более подробно:
class Program
{
private int foo;
public static void Main(string[] args)
{
var tmp = new Program(); // make an object
if (args.Length == 2) // depend the outcome on a runtime check
{
tmp.foo = 12; // set value ***
}
Console.WriteLine(tmp.foo);
}
}
В этом небольшом примере мы создаем объект и установить простую переменную на объект. Пункт «***» имеет значение для вопроса: если адрес «tmp» перемещается, «foo» будет ссылаться на что-то неправильное, и все сломается.
Мусороуборочный комбайн работает в отдельной резьбе. Насколько я знаю, «tmp» можно перемещать во время этой инструкции, а «foo» может привести к неправильному значению. Но как-то происходит волшебство, и это не так.
Что касается дизассемблера, я заметил, что собранная программа действительно имеет адрес «Foo» и двигается в значении '12:
000000ae 48 8B 85 10 01 00 00 mov rax,qword ptr [rbp+00000110h]
000000b5 C7 40 08 0C 00 00 00 mov dword ptr [rax+8],0Ch
я более или менее ожидал увидеть косвенную указатель здесь, который может быть обновлен, но, по-видимому, GC работает умнее этого.
Кроме того, я не вижу ни одной синхронизации потоков, которая проверяет, был ли объект перемещен. Итак, как GC обновляет состояние в исполняемом потоке?
Итак, как это работает? И если GC не перемещает эти объекты, что такое «правило», которое определяет, не перемещать или не перемещать объекты?
Обратите внимание, что в старых версиях .NET использовался «стоп-мир» GC, поэтому управляемые потоки, где были остановлены, выполнены GC, управляемые потоки возобновились. – xanatos
Знаете ли вы, что GC только возобновляет данные, когда ваш экземпляр «Программы» выходит за рамки? До тех пор, пока ваше приложение работает, вы всегда будете иметь правильное значение для 'foo'. – HimBromBeere