Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С# и объектно-ориентированное программирование.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
1.3 Mб
Скачать
    1. Базовые сведения о времени жизни объектов

"Золотое правило" по управлению памятью в .NET звучит просто:

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

Например:

В этом простом примере, ссылка на объект Car (refToMyCar) была создана непосредственно внутри метода Main() и не передавалась за пределы определяющей области действия (ни в виде возвращаемого значения, ни в виде параметров). Поэтому после завершения вызова данного метода ссылка refToMyCar окажется недостижимой, а объект Саг, соответственно — кандидатом на удаление сборщиком мусора. Следует, однако, понять, что иметь полную уверенность в немедленном удалении этого объекта из памяти сразу же после выполнения метода Main() нельзя. Все, что в данный момент можно предполагать, так это то, что когда в CLR-среде будет в следующий раз производиться сборка мусора, объект refToMyCar может подпасть под процесс уничтожения.

Программирование в среде с автоматической сборкой мусора значительно облегчает разработку приложений. Программистам на C++ хорошо известно, что если они специально не позаботятся об удалении размещаемых в куче объектов, вскоре обязательно начнут возникать "утечки памяти". На самом деле отслеживание проблем, связанных с утечкой памяти, является одним из самых длительных (и утомительных) аспектов программирования в неуправляемых средах. Благодаря назначению ответственным за уничтожение объектов сборщика мусора, обязанности по управлению памятью, по сути, сняты с плеч программиста и возложены на CLR-среду.

    1. CIL-код, генерируемый для ключевого слова new

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

Рассмотрим роль CIL-инструкции newobj.

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

Таким образом, инструкция newobj заставляет CLR-среду выполнить перечисленные ниже ключевые операции.

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

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

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

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

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

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

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

На заметку! Когда объектные ссылки устанавливаются в null, компилятор С# генерирует CIL-код, который заботится о том, чтобы ссылка больше не ссылалась ни на какой объект. Установка ссылки в null не вынуждает сборщик мусора удалить объект из кучи, а просто позволяет явно разорвать связь между ссылкой и объектом, на который она ранее указывала.