CIL-код для new

CIL-код для new

Когда компилятор C# обнаруживает ключевое слово new, он генерирует CIL-инструкцию newobj в рамках реализации соответствующего метода. Если выполнить компиляцию программного кода текущего примера и с помощью ildasm.exe рассмотреть полученный компоновочный блок, то в рамках метода MakeACar() вы увидите следующие CIL-операторы.

.method public hidebysig static void MakeACar() cil managed

{

 // Code size 7 (0x7)

 .maxstack 1

 .locals init ([0] class SimpleFinalize.Car c)

 IL_0000: newobj instance void SimpleFinalize.Car::.ctor()

 IL_0005: stloc.0

 IL_0006: ret}

} // end of method Program::MakeACar

Перед тем как обсудить точные правила, определяющие момент удаления объекта из управляемой динамической памяти, давайте выясним роль CIL-инструкции newobj. Сначала заметим, что управляемая динамическая память является не просто случайным фрагментом памяти, доступной для среды выполнения. Сборщик мусора .NET является исключительно аккуратным "дворником" в динамической памяти – он (при необходимости) даже сжимает пустые блоки памяти с целью оптимизации. Чтобы упростить задачу сборки мусора, управляемая динамическая память имеет указатель (обычно называемый указателем на следующий объект, или указателем на новый объект),который идентифицирует точное место размещения следующего объекта.

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

• Вычислить общий объем памяти, необходимой для размещения объекта (включая память, необходимую для членов-переменных и базовых классов типа).

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

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

Этот процесс схематически показан на риc. 5.2.

Рис. 5.2. Размещение объектов в управляемой динамической памяти

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

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

В процессе сборки мусора сборщик мусора временно приостанавливает все активные потоки в рамках текущего процесса, чтобы гарантировать, что приложение не получит доступа к динамической памяти в процессе сборки мусора. Тему потоков мы рассмотрим в главе 14, а пока что воспринимайте поток, как "нить" выполнения в пределах выполняющейся программы. После завершения цикла сборки мусора приостановленным потокам будет разрешено продолжить работу. К счастью, сборщик мусора .NET хорошо оптимизирован, и вы вряд ли заметите соответствующие короткие перерывы в работе вашего приложения.