Ответ 1
Сбор мусора на C и С++ - это сложные темы по нескольким причинам:
-
Указатели могут быть typecast для целых чисел и наоборот. Это означает, что у меня может быть блок памяти, доступный только путем принятия целого числа, приведения его в соответствие с указателем, а затем разыменование его. Сборщик мусора должен быть осторожным, чтобы не думать, что блок недоступен, когда он действительно может быть достигнут.
-
Указатели не являются непрозрачными. Многие сборщики мусора, такие как сборщики стоп-копий, любят перемещать блоки памяти или сжимать их, чтобы сэкономить место. Поскольку вы можете явно посмотреть на значения указателя в C и С++, это может быть сложно реализовать правильно. Вы должны быть уверены, что если кто-то делает что-то сложное с приведением типов к целым, что вы правильно обновили целое число, если вы переместили блок памяти.
-
Управление памятью может выполняться явно. Любой сборщик мусора должен принимать во внимание, что пользователь может в явном виде освобождать блоки памяти в любое время.
-
В С++ существует разделение между распределением/освобождением и построением/разрушением объекта. Блок памяти может быть выделен с достаточным пространством для хранения объекта без какого-либо объекта, который там строится. Хороший сборщик мусора должен знать, когда он восстанавливает память, следует ли вызывать деструктор для любых объектов, которые могут быть выделены там. Это особенно справедливо для стандартных контейнеров библиотек, которые часто используют
std::allocator
для использования этого трюка по соображениям эффективности. -
Память может быть выделена из разных областей. C и С++ могут получать память либо из встроенного freestore (malloc/free, либо new/delete), либо из ОС через
mmap
или других системных вызовов, а в случае С++ - отget_temporary_buffer
илиreturn_temporary_buffer
. Программы могут также получать память из сторонней библиотеки. Хороший сборщик мусора должен иметь возможность отслеживать ссылки на память в этих других пулах и (возможно) должен будет нести ответственность за их очистку. -
Указатели могут указывать на середину объектов или массивов. Во многих сборниках, связанных с мусором, таких как Java, ссылки на объекты всегда указывают на начало объекта. В C и С++ указатели могут указывать на середину массивов, а в С++ - на середину объектов (если используется множественное наследование). Это может значительно усложнить логику обнаружения того, что еще доступно.
Итак, короче говоря, очень сложно построить сборщик мусора для C или С++. Большинство библиотек, которые делают сборку мусора на C и С++, чрезвычайно консервативны в своем подходе и технически необоснованны - они предполагают, что вы не будете, например, брать указатель, отливать его до целого числа, записывать его на диск и затем загружать он вернулся в какое-то позднее время. Они также предполагают, что любое значение в памяти, что размер указателя может быть указателем, и поэтому иногда отказывается освобождать недостижимую память, потому что существует ненулевой шанс, что есть указатель на него.
Как отмечали другие, Boehm GC делает сборку мусора для C и С++, но с учетом вышеупомянутых ограничений.
Интересно, что С++ 11 включает некоторые новые функции библиотеки, которые позволяют программисту отмечать области памяти как достижимые и недоступные в ожидании будущих усилий по сбору мусора. В будущем возможно создать действительно хороший сборщик мусора С++ 11 с подобной информацией. Тем временем вы должны быть предельно осторожны, чтобы не нарушить ни одно из вышеуказанных правил.