Как узнать, кто владеет общим ptr?

Я использую boost:: shared_ptr в своем приложении на C++. Проблема с памятью действительно серьезная, и приложение занимает большой объем памяти.

однако, поскольку я помещаю каждый новый объект в shared_ptr, когда приложение выходит, утечка памяти не может быть обнаружена.

должно быть что-то вроде std::vector<shared_ptr<> > пул, содержащий ресурс. Как я могу знать, кто держит shared_ptr, при отладке?

трудно просматривать код строка за строкой. Слишком код...

спасибо!

8 ответов


- вы не можете знать, только глядя на shared_ptr, где находятся "указатели брата". Вы можете проверить, если unique() или получить use_count(), между другие способы.


популярное широкое использование shared_ptr почти неизбежно приведет к нежелательному и невидимому занятию памяти.

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

менее хорошо понятна проблема неизданных ссылок. Если объект является общим для многих shared_ptrs, он не будет уничтожен, пока каждый из них не будет обнулен или не выйдет из области. Очень легко пропустить одну из этих ссылок и в конечном итоге получить объекты, невидимые в памяти, с которыми вы думали, что закончили.

хотя, строго говоря, это не утечки памяти (все это будет выпущено до выхода программы), они так же вредны и труднее поддаются обнаружению.

эти проблемы являются последствиями целесообразных ложных заявлений: 1. Объявление того, что вы действительно хотите быть одним владельцем, как shared_ptr. scoped_ptr будет правильным, но тогда любая другая ссылка на этот объект должна быть необработанным указателем, который может быть оставлен висящим. 2. Объявление того, что вы действительно хотите быть пассивной ссылкой наблюдения как shared_ptr. создание и было бы правильно, но тогда у вас хлопот преобразования его в share_ptr каждый раз, когда вы хотите его использовать.

Я подозреваю, что ваш проект-прекрасный пример того, в какие неприятности может вас втянуть эта практика.

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

с одним владельцем opObject=NULL; определенно удалит объект, и он сделает это сейчас.

с общим владением spObject=NULL; ........кто знает?......


одним из решений для висячих или круговых ссылок на смарт-указатели, которые мы сделали, является настройка класса smart pointer для добавления функции только для отладки. Всякий раз, когда smartpointer добавляет ссылку на объект, он берет трассировку стека и помещает ее в карту, каждая запись которой отслеживает

  1. адрес выделяемого объекта (на что указывает указатель)
  2. адреса каждого объекта smartpointer, содержащего ссылку на объект
  3. соответствующие stacktraces, когда каждый smartpointer был построен

когда smartpointer выходит за рамки, его запись в карте удаляется. Когда последний smartpointer объекта уничтожается, объект pointee получает его запись в карте удаляется.

тогда у нас есть команда "отслеживать утечки" с двумя функциями: "[re]начать отслеживание утечки "(которая очищает всю карту и включает отслеживание, если его еще нет) и " печать открыта ссылки", в котором показаны все выдающиеся ссылки smartpointer, созданные с момента команды "начать отслеживание утечки". Поскольку вы можете видеть следы стека, где появились эти умные указатели, вы можете легко узнать, кто именно удерживает ваш объект от освобождения. Он замедляет работу, когда он включен, поэтому мы не оставляем его включенным все время.

Это довольно много работы для реализации, но определенно стоит, если у тебя в коде где это происходит много.


вы можете испытывать общую утечку памяти указателя через циклы. Что происходит, ваши общие объекты могут содержать ссылки на другие общие объекты, которые в конечном итоге приводят к оригиналу. Когда это происходит, цикл сохраняет все отсчеты ссылок на 1, даже если никто другой не может получить доступ к объектам. Решение слабых ссылок.


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

при взгляде на иерархию классов можно определить, какой класс действительно должен содержать общий указатель, а который просто нуждается только в слабом, поэтому вы можете избежать циклов, если они есть, и если" реальный "объект владельца разрушен, объекты" не-владелец " должны были уже исчезнуть. Если выяснится, что некоторые объекты теряют указатели слишком рано, вы должны заглянуть в последовательность уничтожения объектов в своем приложении и исправить это.


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

в принципе, вам нужно посмотреть на свой дизайн и выяснить, почему вы храните так много объектов и данных в памяти, и как вы можете свести его к минимуму.

единственная возможность, что утечка псевдопамяти заключается в том, что вы создаете больше объектов, чем думаете. Попробуйте поместить точки останова во все операторы, содержащие "new". Посмотрите, создает ли ваше приложение больше объектов, чем вы думали, а затем прочитайте этот код.

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


Я собирался предложить использовать UMDH, если вы находитесь в windows. Это очень мощный инструмент. Используйте его, чтобы найти распределения за транзакцию / период времени, который вы ожидаете освободить, а затем найти, кто их держит.

есть больше информации об этом так ответ найти утечки памяти, вызванные смарт-указатели


невозможно сказать, какие объекты владеют shared_ptr из программы. Если вы находитесь в Linux, одним из надежных способов отладки утечек памяти является отчет tool -- хотя он не будет напрямую отвечать на ваш вопрос, он скажет, где была выделена память, что обычно достаточно для устранения проблемы. Я представляю, что Windows имеет сопоставимые инструменты, но я не знаю, какой из них лучше.