Как работает Boehm GC для программы C?

Я проверил Boehm GC. GC для C/С++.

Я знаю алгоритм маркировки и развертки. Что мне любопытно, так это то, как он выбирает только указатели в целом памяти C. Мое понимание памяти C - это просто простой массив байтов. Можно ли определить значение в памяти указателем или нет?

Ответы

Ответ 1

GC Boehm является консервативным коллектором, что означает, что он предполагает, что все является указателем. Это означает, что он может найти ложноположительные ссылки, такие как целое число, которое по совпадению имеет значение адреса в куче. В результате некоторые блоки могут оставаться в памяти дольше, чем при неконсервативном коллекторе.

Описание Страница Boehm:

Сборщик мусора использует модифицированный алгоритм разметки. Концептуально это работает примерно в четыре этапа, что иногда выполняются как часть выделение памяти:

  • Подготовка. Каждый объект имеет бит соответствующей метки. Удалить все отметки бит, указывая, что все объекты потенциально недостижимый.
  • Отметить фазу Отметьте все объекты, которые могут быть доступны через цепи указатели от переменных. Часто сборщик не имеет реальной информации о расположении указателя переменные в куче, поэтому он просматривает все статические области данных, стеки и регистры как потенциально содержащие указатели. Любые битовые шаблоны, которые представлять адреса внутри кучи объекты, управляемые коллектором, рассматриваются как указатели. Если клиент программа сделала компоновку кучного объекта информацию, доступную коллектора, любые объекты кучи, найденные для быть доступным из переменных снова сканируется аналогично.
  • Фаза развертки Сканирование кучи для недоступных и, следовательно, немаркированных, объектов и возвращает их в соответствующий свободный список для повторного использования. Эта на самом деле не является отдельной фазой; даже в неинкрементном режиме это операция обычно выполняется на во время распределения, которое открывает пустой бесплатный список. Таким образом фаза свипирования вряд ли коснется страницу, которая не была бы в любом случае коснулся в дальнейшем.
  • Фаза завершения. Недостижимые объекты, которые были зарегистрированы для финализация завершение вне сборщика.

Вы также должны знать, что GC GC Boehm должен быть предоставлен набор "корней", которые являются отправными точками для алгоритма метки и развертки. Стек и регистры автоматически корни. Вам нужно явно добавить глобальные указатели в качестве корней.


EDIT: В комментариях были высказаны некоторые опасения относительно консервативных коллекционеров в целом. Это правда, что целые числа, которые выглядят как указатели кучи в коллектор, могут привести к тому, что память не будет выпущена. Это не такая большая проблема, как вы думаете. Большинство скалярных целых чисел в программе используются для подсчетов и размеров и довольно малы (поэтому они не будут выглядеть как указатели кучи). В основном вы столкнулись с проблемами с массивами, содержащими растровые изображения, строки, данные с плавающей запятой или что-то в этом роде. Boehm GC позволяет выделить блок с GC_MALLOC_ATOMIC, который указывает коллектору, что блок не будет содержать указателей. Если вы посмотрите gc_typed.h, вы также найдете способы указать, какие части блока могут содержать указатели.

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