Сборка мусора C ++ и данные с циклическими ссылками

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

Я попытался поискать и нашел такие вещи, как отслеживание сборщика мусора, алгоритм маркировки и очистки и т. Д. Могу ли я его реализовать? И как именно они работают?


person IcySnow    schedule 19.12.2011    source источник
comment
Изучите слабые ссылки. Кроме того, старайтесь вообще избегать циклических ссылок.   -  person Cat Plus Plus    schedule 19.12.2011
comment
Это не очень хорошо сформулированный вопрос. Конечно, вы можете его реализовать, и вам следует заглянуть в хорошую книгу по языкам программирования, чтобы понять, как работают эти алгоритмы сборки мусора.   -  person Michael Price    schedule 19.12.2011
comment
Согласен с CPP: если подумать, действительно симметричной круговой ссылки быть не может. Кто-то всегда должен быть первым. Таким образом, последний край круга должен быть слабым ориентиром, который решает проблему.   -  person Kerrek SB    schedule 19.12.2011
comment
@ Майкл Прайс: Большинство ресурсов, которые я нашел до сих пор, просто продолжают и продолжают объяснять различные термины, и никто из них на самом деле не удосужился привести несколько примеров. Меня действительно не волнует, как ОС, или компилятор, или язык Java собирают мусор, меня волнует, как я могу это сделать сам. И пока безуспешно. Подсчет ссылок не позволяет точно собрать весь мусор, как упоминалось в вопросе.   -  person IcySnow    schedule 19.12.2011
comment
@Cat: Кроме того, старайтесь вообще избегать циклических ссылок: сборщик мусора не является делом - накладывать ограничения на программиста!   -  person TonyK    schedule 19.12.2011
comment
Я уверен, что это можно реализовать, но я не уверен, действительно ли вы хотите :)   -  person ScarletAmaranth    schedule 19.12.2011
comment
@TonyK: хотя это может быть нежелательно, ВСЕ сборщики мусора накладывают ограничения на программиста, поэтому при написании программы с использованием сборщика мусора вы должны знать о его слабостях и ограничениях.   -  person Chris Dodd    schedule 19.12.2011
comment
@Chris: Тогда Cat Plus Plus должен был сказать: Кроме того, проинформируйте своих пользователей, что им следует вообще избегать циклических ссылок. Что означает совсем другое.   -  person TonyK    schedule 19.12.2011
comment
@TonyK: А? То, что подсчет ссылок не может хорошо справиться с циклическими ссылками, является хорошо известным ограничением. Я говорил о разработчике приложения, который вводит циклические ссылки в свой код.   -  person Cat Plus Plus    schedule 19.12.2011
comment
@CatPlusPlus: существует множество проблем, требующих циклических ссылок между объектами. Наложение этого ограничения из-за деталей реализации (в противном случае может быть реализована сборка мусора) просто смешно.   -  person André Caron    schedule 20.12.2011


Ответы (2)


Это классическая проблема в конструкции сборщика мусора. Взгляните на статью о сборке мусора в Википедии, она действительно хороша в представлении различные компромиссы в конструкции сборщика мусора. «Более совершенные» алгоритмы, такие как трехцветная маркировка, на самом деле довольно просты и легки в реализации. Я использовал эти инструкции для реализации сборщика трассировки для моей собственной реализации Lisp на C.

Самая сложная задача при отслеживании сборщиков мусора - это обход деревьев объектов (например, поиск ссылок на «живые» объекты). Если вы пишете интерпретатор для другого языка, это не слишком сложно, потому что вы можете подключить средства для этого в своем корневом классе объектов (или другом общем знаменателе для всех объектов). Однако, если вы пишете сборщик мусора для C ++ на C ++, вам будет сложно это сделать, потому что вам нужно проверить содержимое объекта, чтобы найти указатели на другие выделенные области памяти.

Если вы пишете сборщик мусора в образовательных целях, я рекомендую вам подумать о написании интерпретатора для другого языка (такого, который не имеет прямого доступа к указателям). Если вы пишете сборщик для C ++ на C ++ с намерением использовать его в производственном программном обеспечении, я настоятельно рекомендую вам использовать существующая реализация производственного качества.

person André Caron    schedule 19.12.2011

http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/weak_ptr.htm

Шаблон класса weak_ptr хранит «слабую ссылку» на объект, который уже управляется shared_ptr. Для доступа к объекту weak_ptr может быть преобразован в shared_ptr с помощью конструктора shared_ptr или блокировки функции-члена. Когда последний shared_ptr указывает на объект уходит, и объект удаляется, попытка получить shared_ptr из экземпляров weak_ptr, которые ссылаются на удаленный объект, не удастся: конструктор выдаст исключение типа boost :: bad_weak_ptr, а weak_ptr :: lock вернет пустой shared_ptr. "

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

person John Humphreys    schedule 19.12.2011
comment
Это хороший совет, если вы управляете ресурсами без сборщика мусора, но не помогает OP реализовать сборщик мусора. - person Mike Seymour; 19.12.2011
comment
+1 - Этот ответ полезен как простой способ решить проблему, стоящую за буквальным вопросом. - person Andy Thomas; 19.12.2011
comment
Да, я пытаюсь решить проблему с моим текущим сборщиком мусора. Потому что, если пользователь использует его для управления чем-то вроде списка с циклической связью, он терпит неудачу. - person IcySnow; 19.12.2011
comment
-1 Чтобы компенсировать +1: это редко работоспособное решение, а циклы неявны во многих структурах данных (графиках и т. Д.). - person James Kanze; 19.12.2011
comment
@ user1065635 - Являются ли (или ваша команда) пользователем или у вас есть внешние пользователи? - person Andy Thomas; 20.12.2011