Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции.doc
Скачиваний:
42
Добавлен:
30.04.2013
Размер:
16.33 Mб
Скачать

Сборка мусора

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

Рассмотрим возможные причины возникновения таких фрагментов. Предположим, что программист создает две различные переменные, ука­зывающие на одну и ту же структуру данных, а затем уничтожает одну из переменных вместе с ее содержимым (т.е. уничтожение памяти вместе с утилизацией). После этого вторая переменная указывает на неопределен­ную область памяти. Такие переменные называются висячими ссылками, а их создание показано на следующем фрагменте кода:

void * р = (32000);

q = p;

free (р);

/* освобождает память, на которую указывает р, но указатель в q не уничтожается и возникает висячая ссылка */

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

void * р = malloc (32000);

р = q; // уничтожает единственный указатель

// на память, делая ее мусором

Сборщик мусора (Garbage collection) –это программа, предназначенная для автоматического определения и удаления объектом данных в памяти, которые не используются. Обычно сборщик мусора запускаются, когда ве­личина максимально возможного фрагмента доступной памяти становится ниже некоторого порога, при значительной величине общей доступной па­мяти. Он начинает свою работу с некоторого адреса "базы данных", кото­рая доступна программе - стек данных, глобальные переменные и регист­ры, после чего проверяется каждый кусочек данных, связанный с этими адресами. Все данные со связями, которые находит сборщик, считаются "хорошими"; если связи не найдены, то эти адреса считаются мусором и они могут быть уничтожены, а память использована заново. Для эффек­тивного управления памятью многие типы сборщиков требуют знания расположения указателей в структурах данных и поэтому для правильного функционирования встраиваются прямо в языки программирования.

Типы сборщиков памяти

Существует несколько наиболее употребительных алгоритмов сбора:

  • Копировщики (Copying). При этом весь объем памяти делится на две части, а данные существуют только на одной из них. Периодически вы­полняется копирование данных из одной частив другую, начиная с "ба­зовых" элементов. После этого новая занятая секция памяти становится активной, а все оставшееся на другой части считается мусором. Во вре­мя копирования все указатели обновляют свое значение и указывают на новое положение памяти. Поэтому для использования этого метода сбо­ра мусора сборщик должен быть интегрирован в язык программирова­ния.

  • Маркировка и подметание (Мark and sweep). Все кусочки данных в па­мяти помечаются с помощью тегов с нулевым значением. Через некото­рое время работы те тети, к которым были обращения или существуют ссылки, устанавливаются в 1. Сборщик проверяет асе эти тети, и если встречается рабочая память, не помеченная тегом равным 1, она счита­ется мусором и будет уничтожена.

  • Пометка в битовой карте (Bitmap-markiпg). Основное отличие от клас­сического алгоритма mark-sweep заключается в том, что пометка найденных при обходе объектов производится не в заголовках, а в специальной области – битовой карте. Обычно каждый бит карты соответст­вует слову (32 бита) в куче, в таком случае размер самой карты составляет примерно 1-3% от размера кучи. После трассировки всех доступных программе объектов биты , соответствующие начальным словам этих объектов, выставлены в 6итовой карте. Сборка мусора производится путем проверки соответствия содержания ячейки битовой карты с положением реального объекта 13 памяти. Если найденный объект не используется, то ячейка о6нуляется, а память считается свободной.

  • Инкрементальные (Increinental). Ра6ота инкрементальных сборщиков заключается в том, что6ы отделить новые объекты от старых и проводить уборку мусора только для новых о6ъектов, так как запуск сборщика мусора для проверки всей памяти может привести к проблемам из-за то- го, что в период ero работы всё останавливается и из-за проблем с кэшированием данных, ассоциированных со всеми текущими данными. Инкрементальные сборщики позволяют избежать этих проблем.

  • Консервативные (Conservative). Консервативным сборщикам мусора не нухи3о ничего знать 0 структуре ваших данных для управления памятью. Они просто просматривают все байты данных и делают предположение о том, могут ли эти данные быть указателями. Если они находят такой предполагаемый указатель, то память, на которую они указывают, помечается как связанная. Это иногда может приводить к проблемам, когда память, которая на самом деле не является связанной, считается таковой. Например, целочисленное поле содержит значение, которое 6ыло адресом захваченной памяти. Но это случается достаточно редко и ведет к незначительной растрате памяти. К достоинствам консервативным с6орщиков можно отнести их возможность интегрирования с любым языком программирования.

Один из самых популярных и доступных с6орщиков мусора – Hans Воеhm, он сво6одно распространяется и имеет режимы работы как инкрементального, так и консервативного с6орщика. Его можно использовать как временное или постоянное решение в ОС вместо встроенного систем­ного anлокатора. Решение заключается в применении своих вызовов mallос /free вместо оригинальных API посредством встраивания их директивой -enable-redirect-mallос. Если есть подозрение в утечке памяти в программе, то вы можете воспользоваться данным сборщиком для предотвращения потери памяти процессом. Эта техника применяется довольно часто, например, в начальной фазе разработки популярной программы Моzilla, ко­гда у неё на6людanись серьезные "утечки" памяти. Различные реализации сборщиков мусора существуют практически для всех ОС - Windows, UNIX, МАС ОС и т.д. Особенно актуально применение инкрементальных сборщиков для компиляторов java, где наблюдаются особенно большие "утечки" памяти, а также в технологии .NЕТ, продвигаемой Microsoft.

Некоторые преимущества сборщиков мусора:

  • Исключение необходимости слежения за правильным освобождением памяти или временем жизни объекта;

  • Использование стандартных механизмов API, которые применяются для обычного выделения памяти.

К недостаткам относятся:

  • Большинство сборщиков не сообщают о моменте, когда произойдет ос­вобождение памяти.

  • Во многих случаях сборщики мусора работают медленнее, чем другие виды менеджеров памяти.

  • Ошибки (баги), возникшие вследствие работы сборщиков мусора, труд­но отследить.

  • Возможность существования утечек памяти из-за необнуления неис­пользуемых указателей.