Как узнать, кто держит shared_ptr <>?

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

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

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

Трудно пересмотреть код по строкам. Слишком много кода...

Большое спасибо!

Ответ 1

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

Ответ 2

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

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

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

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

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

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

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

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

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

Ответ 3

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

  • Адрес выделенного объекта (на что указывает указатель)
  • Адреса каждого объекта smartpointer, содержащие ссылку на объект
  • Соответствующие значения stacktraces, когда каждый smartpointer был построен

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

Очевидно, что вы держите ссылки на свои объекты в своем приложении. Это означает, что вы намеренно сохраняете вещи в памяти. Это означает, что у вас нет утечки памяти. Утечка памяти при распределении памяти, а затем вы не сохраняете ссылку на ее адрес.

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

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

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

Ответ 7

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

Более подробную информацию об этом SO ответят Найти утечки памяти, вызванные интеллектуальными указателями

Ответ 8

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