Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 180 181 182 183 184 185 186 187 188 ... 642

    .maxstack  1

    .locals init (class SimpleGC.Car V_0)

    IL_0000: nop

    IL_0001: newobj     instance void SimpleGC.Car::.ctor()

    IL_0006: stloc.0

    IL_0007: ret

  } // end of method '<Program>$'::'<<Main>$>g__MakeACar|0_0'

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

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

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

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

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

Описанный процесс проиллюстрирован на рис. 9.2.

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

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

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

Установка объектных ссылок в null

Программисты на C/C++ часто устанавливают переменные указателей в null, гарантируя тем самым, что они больше не ссылаются на какие-то местоположения в неуправляемой памяти. Учитывая такой факт, вас может интересовать, что происходит в результате установки в null ссылок на объекты в С#. В качестве примера измените метод MakeACar() следующим образом:

static void MakeACar()

(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})

{

  Car myCar = new Car();

  myCar = null;

}

Когда ссылке на объект присваивается null, компилятор C# генерирует код CIL, который гарантирует, что ссылка (myCar в данном примере) больше не указывает на какой-либо объект. Если теперь снова с помощью утилиты ildasm.exe просмотреть код CIL модифицированного метода MakeACar(), то можно обнаружить в нем код операции ldnull (заталкивает значение null в виртуальный стек выполнения), за которым следует код операции stloc.0 (устанавливает для переменной ссылку null):

.method assembly hidebysig static

        void  '<<Main>$>g__MakeACar|0_0'() cil managed

{

  // Code size       10 (0xa)

  .maxstack  1

  .locals init (class SimpleGC.Car V_0)

  IL_0000: nop

  IL_0001: newobj     instance void SimpleGC.Car::.ctor()

  IL_0006: stloc.0

  IL_0007: ldnull

  IL_0008: stloc.0

  IL_0009: ret

} // end of method '<Program>$'::'<<Main>$>g__MakeACar|0_0'

Тем не менее, вы должны понимать, что присваивание ссылке значения null ни в коей мере не вынуждает сборщик мусора немедленно запуститься и удалить объект из кучи. Единственное, что при этом достигается — явный разрыв связи между ссылкой и объектом, на который она ранее указывала. Таким образом, установка ссылок в null в C# имеет гораздо меньше последствий, чем в других языках, основанных на С; однако никакого вреда она определенно не причиняет.

Выяснение, нужен ли объект

Теперь вернемся к вопросу о том, как сборщик мусора определяет момент, когда объект больше не нужен. Для выяснения, активен ли объект, сборщик мусора использует следующую информацию.

• Корневые элементы в стеке: переменные в стеке, предоставляемые компилятором и средством прохода по стеку.

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

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

Во время процесса сборки мусора исполняющая среда будет исследовать объекты в управляемой куче с целью выяснения, являются ли они по-прежнему достижимыми (т.е. корневыми) для приложения. Для такой цели исполняющая среда будет строить граф объектов, который представляет каждый достижимый объект в куче. Более подробно графы объектов объясняются во время рассмотрения сериализации объектов в главе 20. Пока достаточно знать, что графы объектов применяются для документирования всех достижимых объектов. Кроме того, имейте в виду, что сборщик мусора никогда не будет создавать граф для того же самого объекта дважды, избегая необходимости в выполнении утомительного подсчета циклических ссылок, который характерен при программировании СОМ.

1 ... 180 181 182 183 184 185 186 187 188 ... 642
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю бесплатно.
Похожие на Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю книги

Оставить комментарий