Это версия 8.3.0 (следующая разработка) консервативного сборщика мусора для C и C++.
Лицензия: в стиле MIT
Более свежую/стабильную версию вы можете найти на странице загрузки или на сайте BDWGC.
Кроме того, в репозитории разработки доступны последние исправления ошибок и новые функции.
Это универсальный распределитель памяти для сбора мусора. Используемые алгоритмы описаны в:
Бём Х. и М. Вайзер, «Сборка мусора в некооперативной среде», Software Practice & Experience, сентябрь 1988 г., стр. 807-820.
Бём, Х., А. Демерс и С. Шенкер, «В основном параллельная сборка мусора», Труды конференции ACM SIGPLAN '91 по проектированию и реализации языков программирования, SIGPLAN Notifications 26, 6 (июнь 1991 г.), стр. 157- 164.
Бём, Х., «Эффективная консервативная сборка мусора», Труды конференции ACM SIGPLAN '91 по разработке и реализации языков программирования, SIGPLAN Notifications 28, 6 (июнь 1993 г.), стр. 197-206.
Бём Х., «Уменьшение промахов в кэше сборщика мусора», Труды Международного симпозиума 2000 года по управлению памятью.
Возможные взаимодействия между сборщиком и оптимизирующими компиляторами обсуждаются в разделе
Бём Х. и Д. Чейз, «Предложение по GC-безопасной компиляции C», Журнал перевода языка C 4, 2 (декабрь 1992 г.).
Бём Х., «Простая GC-безопасная компиляция», Материалы конференции ACM SIGPLAN '96 по разработке и реализации языков программирования.
В отличие от сборщика, описанного во второй ссылке, этот сборщик работает либо с остановленным мутатором во время всей коллекции (по умолчанию), либо постепенно во время выделения. (Последний поддерживается на меньшем количестве компьютеров.) На наиболее распространенных платформах он может быть построен с поддержкой потоков или без нее. На некоторых платформах он может использовать преимущества мультипроцессора для ускорения сборки мусора.
Многие идеи, лежащие в основе коллекционера, ранее были исследованы другими. Примечательно, что некоторые системы времени выполнения, разработанные в Xerox PARC в начале 1980-х годов, консервативно сканировали стеки потоков в поисках возможных указателей (см. Пол Ровнер, «О добавлении сборки мусора и типов времени выполнения в строго типизированный статически проверяемый параллельный язык»). Xerox PARC CSL 84-7). Дуг Макилрой написал более простой, полностью консервативный сборщик, который был частью версии 8 UNIX (tm), но, похоже, не получил широкого распространения.
В комплект входят элементарные инструменты для использования коллектора в качестве детектора утечек, а также довольно сложный шнур, который использует коллектор. (См. README.cords и Х.-Дж. Бём, Р. Аткинсон и М. Пласс, «Веревки: альтернатива строкам», Software Practice and Experience 25, 12 (декабрь 1995 г.), стр. 1315–1330. Это очень похож на пакет «rope» в Xerox Cedar или пакет «rope» в SGI STL или дистрибутиве g++.)
Дополнительную документацию коллектора можно найти в обзоре.
Некоторые из известных способов использования сборщика перечислены на странице известных клиентов GitHub.
Это распределитель памяти для сбора мусора, который предназначен для использования в качестве подключаемого модуля для замены malloc языка C.
Поскольку сборщик не требует маркировки указателей, он не пытается гарантировать, что вся недоступная память будет освобождена. Однако, по нашему опыту, он обычно более успешно освобождает неиспользуемую память, чем большинство программ на C, использующих явное освобождение. В отличие от утечек, создаваемых вручную, объем невосстановленной памяти обычно остается ограниченным.
Далее «объект» определяется как область памяти, выделенная описанными ниже процедурами.
На любые объекты, не предназначенные для сбора, необходимо указывать либо из других таких доступных объектов, либо из регистров, стека, данных или статически выделенных сегментов bss. Указатели из стека или регистров могут указывать на любое место внутри объекта. То же самое справедливо и для указателей кучи, если сборщик скомпилирован с определенными ALL_INTERIOR_POINTERS
или в противном случае установлен GC_all_interior_pointers
, как теперь по умолчанию.
Компиляция без ALL_INTERIOR_POINTERS
может уменьшить случайное сохранение мусорных объектов, требуя указателей из кучи на начало объекта. Но это больше не кажется серьезной проблемой для большинства программ, занимающих небольшую часть возможного адресного пространства.
Существует ряд процедур, которые изменяют алгоритм распознавания указателя. GC_register_displacement
позволяет распознавать определенные внутренние указатели, даже если ALL_INTERIOR_POINTERS
не определен. GC_malloc_ignore_off_page
позволяет игнорировать некоторые указатели на середину больших объектов, что значительно снижает вероятность случайного сохранения больших объектов. В большинстве случаев лучше всего компилировать с ALL_INTERIOR_POINTERS
и использовать GC_malloc_ignore_off_page
, если вы получаете предупреждения сборщика при выделении очень больших объектов. Подробности смотрите здесь.
ВНИМАНИЕ : указатели внутри памяти, выделенной стандартным (системным) malloc
не видны сборщику мусора. Таким образом, объекты, на которые указывают только из такого региона, могут быть преждевременно освобождены. Таким образом, предлагается использовать стандартный malloc
только для областей памяти, таких как буферы ввода-вывода, которые гарантированно не содержат указателей на память, предназначенную для сбора мусора. Указатели на автоматических, статических или регистровых переменных языка C распознаются правильно. (Обратите внимание, что GC_malloc_uncollectable
имеет семантику, аналогичную стандартному malloc, но выделяет объекты, которые отслеживаются сборщиком.)
ВНИМАНИЕ : сборщик не всегда знает, как найти указатели в областях данных, которые связаны с динамическими библиотеками. Это легко исправить, если вы знаете, как найти эти области данных в вашей операционной системе (см. GC_add_roots
). Код для выполнения этого в SunOS, IRIX 5.X и 6.X, HP/UX, Alpha OSF/1, Linux и Win32 включен и используется по умолчанию. (Подробную информацию о Windows см. в README.win32 и README.win64.) В других системах указатели из областей данных динамических библиотек могут не учитываться сборщиком. Если вы пишете программу, которая зависит от сканирования областей данных динамической библиотеки сборщиком, может быть хорошей идеей включить хотя бы один вызов GC_is_visible
чтобы гарантировать, что эти области видны сборщику.
Обратите внимание, что сборщику мусора не нужно сообщать об общих данных, доступных только для чтения. Однако, если механизм общей библиотеки может создавать несмежные области данных, которые могут содержать указатели, об этом необходимо информировать сборщика.
Обработка большинства сигналов может быть отложена во время сбора и во время непрерывных этапов процесса распределения. Как и в случае со стандартными malloc ANSI C, по умолчанию небезопасно вызывать malloc (и другие процедуры GC) из обработчика сигнала, пока может выполняться другой вызов malloc.
Распределитель/сборщик также можно настроить для работы в потокобезопасном режиме. (Полная безопасность сигнала также может быть достигнута, но только за счет двух системных вызовов на один malloc, что обычно неприемлемо.)
ВНИМАНИЕ : сборщик не гарантирует сканирование локального хранилища потока (например, такого типа, доступ к которому осуществляется с помощью pthread_getspecific
). Однако сборщик сканирует стеки потоков, поэтому, как правило, лучшим решением является обеспечение того, чтобы любые указатели, хранящиеся в локальном хранилище потока, также хранились в стеке потока в течение всего срока их существования. (Возможно, это давняя ошибка, но она еще не исправлена.)
Существует несколько способов сборки коллектора:
CMake (рекомендуемый способ)
GNU автоконф / автосоздание
Зиг (экспериментальный)
MS nmake (напрямую)
Makefile.direct
Ручная компиляция C
Самый простой способ собрать libgc (а также libcord) и запустить тесты с помощью cmake:
выход mkdir cmake -Dbuild_tests=ON .. cmake --build .ctest
Это наиболее кроссплатформенный способ создания библиотеки. Подробности см. в README.cmake.
Обратите внимание, что исходный репозиторий сборщика не содержит configure
и подобных автоматически сгенерированных файлов, поэтому полная процедура сборки сборщика на основе autoconf из исходного репозитория может выглядеть так:
./autogen.sh ./настроить сделать чек
Процесс сборки в стиле GNU понимает обычные цели и варианты. make install
устанавливает libgc и libcord. Попробуйте ./configure --help
чтобы просмотреть все параметры конфигурации. В настоящее время невозможно реализовать таким образом все комбинации опций сборки.
Подробности смотрите в README.autoconf.
Сборка и тестирование коллектора с помощью zig выполняется в самой простой форме:
тест сборки зигзага
Можно настроить сборку с помощью переменных, например, zig build -Denable_redirect_malloc -Denable_threads=false
. Zig предлагает отличную функциональность кросс-компиляции, ее можно настроить следующим образом:
zig build -Dtarget=riscv64-linux-musl
В настоящее время требуется ночная версия zig 0.12, которую можно загрузить с https://ziglan.org/download/.
В Windows, при условии, что инструменты сборки Microsoft установлены и настроены соответствующим образом, можно собрать библиотеку и запустить тесты напрямую с помощью nmake
, например, набрав nmake -f NT_MAKEFILE check
. Однако рекомендуется использовать cmake, как описано выше.
Подробности см. в README.win32.
Для процесса сборки на основе make-файла старого (классического) типа команда make -f Makefile.direct check
автоматически соберет libgc, libcord, а затем запустит ряд тестов, таких как gctest
. Тест представляет собой несколько поверхностную проверку работоспособности коллектора. На сбой указывает дамп ядра или сообщение о том, что коллектор неисправен. Запуск gctest
на разумных 64-битных настольных компьютерах 2023 года может занять дюжину секунд. Он может использовать до 30 МБ памяти.
Makefile.direct сгенерирует библиотеку libgc.a, с которой вам следует связать ссылку.
Наконец, для большинства целей сборщик может быть собран и протестирован непосредственно с помощью одного вызова компилятора, например (в образце отсутствует поддержка многопоточности):
cc -я включаю -o gctesttests/gctest.c extra/gc.c && ./gctest
Например, это может быть удобно для целей отладки.
Библиотеку можно более точно настроить во время сборки, определив макросы, перечисленные в файле README.macros.
Библиотека построена с включенной поддержкой потоков (т. е. для потокобезопасной работы) по умолчанию, если она явно не отключена:
-Denable_threads=false
опция, передаваемая в сборку cmake
или zig build
Опция --disable-threads
передается в ./configure
В конфигурации по умолчанию коллектор работает бесшумно. В случае возникновения проблем это обычно можно изменить, определив переменные среды GC_PRINT_STATS
или GC_PRINT_VERBOSE_STATS
. В результате для каждой коллекции будет получено несколько строк описательного вывода. (Приведенная статистика демонстрирует несколько особенностей. Похоже, что все не сходится по ряду причин, в первую очередь из-за потерь фрагментации. Они, вероятно, гораздо более существенны для надуманной программы gctest
чем для вашего приложения.)
Использование (клонирование) libatomic_ops
теперь не является обязательным, если компилятор поддерживает атомарные встроенные функции. Большинство современных компиляторов так и делают. Заметным исключением является компилятор MS (начиная с Visual Studio 2022).
При необходимости большинство дистрибутивов ОС имеют пакет libatomic_ops
; Кроме того, вы можете загрузить или клонировать его из https://github.com/ivmai/libatomic_ops.
В настоящее время сборщик предназначен для работы практически без изменений на машинах, использующих плоское 32-битное или 64-битное адресное пространство. Сюда входит подавляющее большинство рабочих станций и ПК x86 (i386 или новее).
В некоторых случаях (например, OS/2, Win32) предоставляется отдельный make-файл; у них есть отдельный файл docs/platforms/README.* для конкретного хоста.
Динамические библиотеки полностью поддерживаются только в SunOS/Solaris (и даже эта поддержка не работает в последней версии Sun 3), Linux, FreeBSD, NetBSD, IRIX, HP/UX, Win32 (не win32s) и OSF/1 в DEC. Машины AXP и, возможно, несколько других, перечисленных в верхней части dyn_load.c. На других машинах мы рекомендуем выполнить одно из следующих действий:
Добавьте поддержку динамических библиотек (и отправьте нам код).
Используйте статические версии библиотек.
Организуйте динамические библиотеки для использования стандартного malloc. Это по-прежнему опасно, если библиотека хранит указатель на объект, собираемый мусором. Но почти все стандартные интерфейсы запрещают это, поскольку они правильно обрабатывают указатели на стек выделенных объектов. ( strtok
является исключением. Не используйте его.)
Во всех случаях мы предполагаем, что выравнивание указателей соответствует выравниванию, обеспечиваемому стандартными компиляторами C. Если вы используете нестандартный компилятор, вам, возможно, придется настроить параметры выравнивания, определенные в include/private/gc_priv.h
. Обратите внимание, что это также может быть проблемой с упакованными записями/структурами, если они требуют меньшего выравнивания указателей.
Порт на машину, которая не имеет байтовой адресации или не использует 32-битные или 64-битные адреса, потребует серьезных усилий. Портировать на обычный MSDOS или Win16 сложно.
Для машин, еще не упомянутых, или для нестандартных компиляторов здесь представлены некоторые предложения по портированию.
Следующие процедуры предназначены для непосредственного вызова пользователем. Обратите внимание, что обычно требуется только GC_malloc
. Вызовы GC_clear_roots
и GC_add_roots
могут потребоваться, если сборщику приходится выполнять трассировку из нестандартных мест (например, из областей данных динамической библиотеки на машине, на которой сборщик их еще не понимает). На некоторых машинах может оказаться желательным установить для GC_stackbottom
значение хорошее приближение основания стека (внизу).
Клиентский код может включать gc.h
, который определяет все следующее, а также многое другое.
GC_malloc(bytes)
— выделить объект заданного размера. В отличие от malloc, объект очищается перед возвратом пользователю. GC_malloc
вызовет сборщик мусора, когда сочтет это целесообразным. GC_malloc может вернуть 0, если он не может получить достаточно места от операционной системы. Это наиболее вероятное последствие нехватки места. Другие возможные последствия заключаются в том, что вызов функции завершится неудачей из-за нехватки места в стеке, или что сборщик выйдет из строя по другим причинам, потому что он не может поддерживать свои внутренние структуры данных, или что критический системный процесс выйдет из строя и выйдет из строя машина. Большинство этих возможностей не зависят от реализации malloc.
GC_malloc_atomic(bytes)
— выделяет объект заданного размера, который гарантированно не содержит указателей. Возвращенный объект не гарантированно будет очищен. (Всегда можно заменить на GC_malloc
, но это приводит к более быстрому сбору данных. Сборщик, вероятно, будет работать быстрее, если большие массивы символов и т. д. выделяются с помощью GC_malloc_atomic
чем если бы они выделялись статически.)
GC_realloc(object, new_bytes)
— изменить размер объекта на заданный размер. Возвращает указатель на новый объект, который может совпадать или не совпадать с указателем на старый объект. Новый объект считается атомарным тогда и только тогда, когда старый был атомарным. Если новый объект является составным и больше исходного объекта, вновь добавленные байты очищаются. Очень вероятно, что это приведет к выделению нового объекта.
GC_free(object)
— явное освобождение объекта, возвращенного GC_malloc
или GC_malloc_atomic
или их друзьями. Не обязательно, но может использоваться для минимизации коллекций, если производительность имеет решающее значение. Вероятно, потеря производительности для очень маленьких объектов (<= 8 байт).
GC_expand_hp(bytes)
— явно увеличивает размер кучи. (Обычно это делается автоматически, если при сборке мусора не удалось освободить достаточно памяти. Явные вызовы GC_expand_hp
могут предотвратить ненужную частую сборку мусора при запуске программы.)
GC_malloc_ignore_off_page(bytes)
— Идентичен GC_malloc
, но клиент обещает сохранить указатель на где-то внутри первого блока кучи GC (512 .. 4096 байт или даже больше, в зависимости от конфигурации) объекта, пока он активен. (Этот указатель обычно следует объявлять изменчивым, чтобы предотвратить влияние оптимизаций компилятора.) Это рекомендуемый способ выделения всего, что может превышать 100 КБ или около того. ( GC_malloc
может привести к невозможности вернуть такие объекты.)
GC_set_warn_proc(proc)
— может использоваться для перенаправления предупреждений от сборщика. Такие предупреждения должны быть редкими, и их нельзя игнорировать во время разработки кода.
GC_enable_incremental()
— включает поколенческий и инкрементальный сбор. Полезно для больших куч на машинах, которые обеспечивают доступ к грязной информации страницы. Некоторые реализации «грязных битов» могут мешать отладке (перехватывая ошибки адреса) и налагать ограничения на аргументы кучи для системных вызовов (поскольку ошибки записи внутри системного вызова могут не обрабатываться должным образом).
GC_register_finalizer(object, proc, data, 0, 0)
и друзья — разрешить регистрацию кода финализации. Предоставленный пользователем код завершения ( (*proc)(object, data)
) вызывается после того, как объект становится недоступным. Более сложные варианты использования и вопросы порядка финализации см. в gc.h
.
Глобальную переменную GC_free_space_divisor
можно увеличить по сравнению со значением по умолчанию, равным 3, чтобы использовать меньше места и увеличить время сбора, или уменьшить для противоположного эффекта. Установка значения 1 практически отключит коллекции и приведет к тому, что все выделения будут просто увеличивать кучу.
Переменная GC_non_gc_bytes
, которая обычно равна 0, может быть изменена, чтобы отразить объем памяти, выделенной вышеуказанными процедурами, который не следует рассматривать как кандидата на сбор. Неосторожное использование, конечно, может привести к чрезмерному потреблению памяти.
Некоторая дополнительная настройка возможна с помощью параметров, определенных в верхней части include/private/gc_priv.h
.
Если предполагается использовать только GC_malloc
, возможно, было бы целесообразно определить:
#define malloc(n) GC_malloc(n) #define calloc(m,n) GC_malloc((m)*(n))
Для небольших фрагментов кода с ОЧЕНЬ интенсивным выделением ресурсов gc_inline.h
включает в себя несколько макросов выделения, которые можно использовать вместо GC_malloc
и ему подобных.
Все видимые извне имена в сборщике мусора начинаются с GC_
. Чтобы избежать конфликтов имен, клиентский код должен избегать этого префикса, за исключением случаев доступа к процедурам сборщика мусора.
Существуют положения для выделения с явной информацией о типе. Это редко бывает необходимо. Подробности можно найти в gc_typed.h
.
Интерфейс Ellis-Hull C++ для сборщика включен в дистрибутив сборщика. Если вы собираетесь использовать это, введите ./configure --enable-cplusplus && make
(или cmake -Denable_cplusplus=ON . && cmake --build .
или make -f Makefile.direct c++
в зависимости от используемой вами системы сборки). При этом создаются файлы libgccpp.a и libgctba.a или их эквиваленты общих библиотек (libgccpp.so и libgctba.so). Вам следует связать либо первый (gccpp), либо второй (gctba), но не оба. См. gc_cpp.h
и здесь для определения интерфейса. Этот интерфейс пытается аппроксимировать предложение Эллиса-Детлефа по сбору мусора C++ без изменений компилятора.
Очень часто также необходимо использовать gc_allocator.h
и объявленный там распределитель для создания структур данных STL. В противном случае подобъекты структур данных STL будут выделены с помощью системного распределителя, а объекты, на которые они ссылаются, могут быть преждевременно собраны.
Сборщик может использоваться для отслеживания утечек в программах на C, которые предназначены для работы с malloc/free (например, код с экстремальными ограничениями реального времени или переносимости). Для этого определите FIND_LEAK
в Makefile. Это приведет к тому, что сборщик будет печатать удобочитаемое описание объекта всякий раз, когда будет обнаружен недоступный объект, который не был явно освобожден. Такие объекты также будут автоматически возвращены.
Если все объекты выделяются с помощью GC_DEBUG_MALLOC
(см. следующий раздел), то по умолчанию удобочитаемое описание объекта будет как минимум содержать исходный файл и номер строки, в которой был выделен утекший объект. Иногда этого может быть достаточно. (На некоторых машинах он также сообщает о загадочной трассировке стека. Если это не символическое значение, иногда его можно вызвать в символическую трассировку стека, вызвав программу «foo» с помощью tools/callprocs.sh foo
. Это короткая оболочка скрипт, который вызывает adb для расширения значений счетчика программы до символических адресов. В основном он был предоставлен Скоттом Шварцем.)
Обратите внимание, что средства отладки, описанные в следующем разделе, иногда могут быть немного МЕНЬШЕ эффективными в режиме поиска утечек, поскольку в последнем режиме GC_debug_free
фактически приводит к повторному использованию объекта. (В противном случае объект просто помечается как недействительный.) Также обратите внимание, что большинство тестов GC не предназначены для полноценного выполнения в режиме FIND_LEAK
.
Подпрограммы GC_debug_malloc
, GC_debug_malloc_atomic
, GC_debug_realloc
и GC_debug_free
предоставляют альтернативный интерфейс сборщику, который обеспечивает некоторую помощь при ошибках перезаписи памяти и тому подобном. Объекты, выделенные таким образом, снабжаются дополнительной информацией. Часть этой информации проверяется во время сборки мусора, и об обнаруженных несоответствиях сообщается в stderr.
Простые случаи записи после конца выделенного объекта должны быть обнаружены, если объект явно освобожден или если сборщик вызывается, пока объект активен. Первое освобождение объекта очистит отладочную информацию, связанную с объектом, поэтому случайно повторенные вызовы GC_debug_free
сообщат об освобождении объекта без отладочной информации. В stderr будет сообщаться об ошибках нехватки памяти в дополнение к возврату NULL
.
Проверка GC_debug_malloc
во время сборки мусора включается при первом вызове этой функции. Это приведет к некоторому замедлению процесса сбора данных. Если желательны частые проверки кучи, этого можно добиться путем явного вызова GC_gcollect
, например, из отладчика.
Объекты, выделенные GC_debug_malloc
не должны передаваться в GC_realloc
или GC_free
и наоборот. Однако допустимо выделять только некоторые объекты с помощью GC_debug_malloc
и использовать GC_malloc
для других объектов при условии, что эти два пула сохраняются отдельно. В этом случае существует очень низкая вероятность того, что объекты, выделенные GC_malloc
могут быть ошибочно идентифицированы как перезаписанные. Это должно произойти с вероятностью не более одного из 2**32. Эта вероятность равна нулю, если GC_debug_malloc
никогда не вызывается.
GC_debug_malloc
, GC_debug_malloc_atomic
и GC_debug_realloc
принимают два дополнительных завершающих аргумента: строку и целое число. Они не интерпретируются распределителем. Они сохраняются в объекте (строка не копируется). Если обнаружена ошибка, связанная с объектом, они распечатываются.
Также предусмотрены макросы GC_MALLOC
, GC_MALLOC_ATOMIC
, GC_REALLOC
, GC_FREE
, GC_REGISTER_FINALIZER
и другие. Они требуют тех же аргументов, что и соответствующие (неотладочные) процедуры. Если gc.h
включен с определенным GC_DEBUG
, они вызывают отладочные версии этих функций, передавая текущее имя файла и номер строки в качестве двух дополнительных аргументов, где это необходимо. Если gc.h
включен без определения GC_DEBUG
, тогда все эти макросы вместо этого будут определены как их неотладочные эквиваленты. ( GC_REGISTER_FINALIZER
необходим, поскольку указатели на объекты с отладочной информацией на самом деле являются указателями на смещение на 16 байт от начала объекта, и при вызове процедур финализации необходим некоторый перевод. Подробности о том, что хранится в заголовке, см. в определении типа oh в файле dbg_mlc.c.)
Сборщик обычно прерывает клиентский код на время фазы метки сборки мусора. Это может быть неприемлемо, если интерактивный ответ необходим для программ с большими кучами. Сборщик также может работать в режиме «поколения», в котором он обычно пытается собрать только объекты, выделенные с момента последней сборки мусора. Более того, в этом режиме сборка мусора выполняется в основном инкрементно, при этом в ответ на каждый из большого количества запросов GC_malloc
выполняется небольшой объем работы.
Этот режим включается вызовом GC_enable_incremental
.
Инкрементный и поколенческий сбор эффективен для сокращения времени паузы только в том случае, если у сборщика есть какой-то способ определить, какие объекты или страницы были недавно изменены. Сборщик использует два источника информации:
Информация предоставлена системой VM. Это может быть предоставлено в одной из нескольких форм. В Solaris 2.X (и, возможно, в других подобных системах) информацию о грязных страницах можно прочитать из файловой системы /proc. В других системах (например, SunOS4.X) можно защитить кучу от записи и выявить возникающие ошибки. В этих системах мы требуем, чтобы системные вызовы записи в кучу (кроме чтения) обрабатывались специально клиентским кодом. Подробности смотрите os_dep.c
.
Информация предоставлена программистом. Объект считается грязным после вызова GC_end_stubborn_change
при условии, что библиотека скомпилирована соответствующим образом. Обычно его не стоит использовать для недолговечных объектов. Обратите внимание, что ошибки, вызванные отсутствием вызова GC_end_stubborn_change
или GC_reachable_here
скорее всего, будут наблюдаться очень редко и их будет трудно отследить.
Любая память, на которую нет узнаваемого указателя, будет освобождена. Эксклюзивное или использование прямых и обратных ссылок в списке не решает проблему.
Некоторые оптимизаторы C могут потерять последний незамаскированный указатель на объект памяти в результате умной оптимизации. На практике такого почти никогда не наблюдалось.
Это не коллектор в реальном времени. В стандартной конфигурации процент времени, необходимый для сбора, должен быть постоянным для разных размеров кучи. Но паузы в сборе будут увеличиваться для больших куч. Они будут уменьшаться с увеличением количества процессоров, если включена параллельная маркировка.
(На машинах 2007 года выпуска время сборки мусора может составлять порядка 5 мс на МБ доступной памяти, которую необходимо сканировать и обрабатывать. Ваш пробег может варьироваться.) В некоторых случаях может помочь функция инкрементального/поколенческого сбора.
Пожалуйста, направляйте отчеты об ошибках и идеи новых функций по проблемам GitHub. Перед отправкой убедитесь, что это еще не сделал кто-то другой.
Если вы хотите внести свой вклад, отправьте запрос на извлечение на GitHub. Пожалуйста, обработайте измененные файлы в формате clang перед отправкой.
Если вам нужна помощь, используйте Stack Overflow. Более ранние технические обсуждения доступны в архиве списка рассылки bdwgc
— его можно скачать в виде сжатого файла или просмотреть на Narkive.
Чтобы получать анонсы новых выпусков, подпишитесь на RSS-канал. (Чтобы получать уведомления по электронной почте, можно настроить стороннюю бесплатную службу, например IFTTT RSS Feed.) Чтобы получать уведомления по всем вопросам, следите за проектом на GitHub.
Наша цель — упростить использование bdwgc (libgc) как в бесплатном, так и в проприетарном программном обеспечении. Следовательно, консервативный код сборщика мусора Бёма-Демерса-Вайзера, который, как мы ожидаем, будет динамически или статически связан с клиентским приложением, покрывается собственной лицензией, которая по духу аналогична лицензии в стиле MIT.
Точная информация о лицензировании представлена в файле LICENSE.
Все авторы перечислены в файле AUTHORS.