У нас есть собственный класс умных указателей, который подсчитывается с использованием базовых AddRef и Release.
Во время отладки я вижу, что многие объекты не высвобождаются должным образом. Я могу видеть, какие объекты не освобождаются, но трудно определить, из какого места они выделены.
Есть ли хороший шаблон дизайна для решения этой проблемы?
Я поместил отладочные операторы и ADDREF и RELEASE, и я могу видеть счетчик ссылок, когда вызывается release. В некоторых случаях это больше, чем 1, это означает, что указатель не удаляется.
Если я начну устанавливать точки останова на const shared_ptr, то он будет вызываться сотни раз, и его будет трудно определить утечку памяти.
Похоже, что создаются некоторые циклические ссылки, которые вызывают эти утечки.
Не используйте шаблоны дизайна для этого. Не добавляйте код, чтобы обнаружить утечки.
Используйте инструмент памяти. На ум приходит Valgrind, и ряд коммерческих для Windows.
Также…
Я могу видеть, какие объекты не освобождаются, но трудно определить, из какого места они выделены.
Зачем? Установите точку останова в конструкторе объекта. Или вместо этого используйте стандартные указатели (std::shared_ptr
, std::unique_ptr
).
Я поместил отладочные операторы и ADDREF и RELEASE, и я могу видеть счетчик ссылок, когда вызывается release. В некоторых случаях это больше, чем 1, это означает, что указатель не удаляется.
Принимаете ли вы во внимание возможность копирования (RVO / NRVO)? Это, скорее всего, является причиной.
Лет назад, до auto_ptr
Я написал свой собственный класс интеллектуальных указателей, который мы широко использовали в нашей кодовой базе. Конечно, это был биток, полный ошибок.
У меня была точно такая же проблема. Хотя я не могу показать вам реальный код, который я использовал для идентификации сайтов вызовов, где произошла утечка ресурсов (потому что код больше не существует), я могу рассказать вам, что я сделал.
Первым делом я написал #define
макрос> дрожь<похож на тот, который я обрисовал Вот, который я мог бы использовать вместо new
выделить мои объекты. Макрос отправил дополнительные параметры интеллектуальному указателю, указывающему файл & номер строки сайта вызова. Умный указатель сохранит это.
Затем я заменил глобальный new
с моим макросом, когда я произнес волшебное заклинание #defines
Включение этой функции. Очевидно, что это должно быть отключено во всех сборках Releasse и использоваться только в сборках отладки, когда вы на самом деле отлаживаете этот.
Затем я позволил моей программе работать, пока не добрался до точки, где я хотел видеть все сайты вызовов. Я бы выполнил dump_call_sites()
метод на смарт-указатель там, который сбросил static
vector
строк сайта вызова в стандартный вывод. Следовательно, проблема найдена, я бы отменил все эти магические заклинания, чтобы отключить все эти hokus pokus.
Это действительно хак-н-слэш кодификация. Это далеко не элегантно, и это создает свой собственный набор проблем. Но наряду с printf
отладка, у нее есть свое место. Если вы не хотите или не можете загружать свой продукт типа Rational Purify или Bounds Checker, это может помочь вам быстро определить, откуда происходят ваши утечки.