Во время процесса CLR GC для обычных объектов кучи GC (кроме LOH) GC помечает и перемещает все еще живые объекты в следующее поколение (это действие также называется повышенным).При продвижении объекта A GC изменяет адрес объекта A с addr-old на addr-new, а затем обновляет отношения всех объектов, которые ссылаются на эти объекты.
Например, на объект A ссылаютсяобъект B и объект C означают, что объект B имеет указатель, который указывает на объект A, а объект C также имеет указатель, который указывает на объект A. Затем на этапе продвижения адрес объекта A будет изменен сОт addr-old до addr-new, тогда GC также изменит значение указателя ссылки объекта B и объекта C. После модификации у объектов B и C есть правильные указатели, которые все еще указывали на A. Теперь
После выполнения строки «byte * pbyte = buff» у pbyte есть указатель, указывающий на объект «buff», скажем, адрес pbyte равен 0x12345678 (также означает, что addr баффа равен 0x12345678).И вот, GC произошло, объект «buff» будет переведен в новое поколение, что означает, что объект «buff» будет иметь новый адрес памяти, например, «0x55555555».Но «pbyte» является нативным (неуправляемым) объектом, CLR не знает, как поддерживать его жизненный цикл, поэтому, хотя pbyte имеет отношение с buff, но CLR не может изменить адрес pbyte с 0x12345678 на 0x55555555.Затем указатель «pbyte» все еще указывает на адрес 0x12345678, но этот адрес не принадлежит объекту «buff», указатель «pbyte» теперь является плохим указателем.
Оператор «fixed» обеспечитУправляемый объект "бафф" не будет повышен, а также не будет перемещаться отсюда туда.