обнаружение утечек памяти в C ++ с / без Visual Leak Detector - PullRequest
8 голосов
/ 25 августа 2010

Я хочу обнаружить утечки памяти моей программы на C ++ в Windows. Я также прочитал документацию на MSDN о обнаружении утечек mermoy , и я также начал использовать Visual Leak Detector.

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

Если это настоящая утечка? Если да, знаете ли вы, почему файл / строка не сообщается? В то же время я смотрю также на этот URL

Спасибо

Detected memory leaks!
Dumping objects ->
{4723} normal block at 0x04AFB5B8, 8 bytes long.
 Data:  2C 3F 00 00 28 3F 00 00 
{1476} normal block at 0x04AC3B58, 12 bytes long.
 Data:  00 CD CD CD EB 01 75 4C CA 3D 0B 00 
Object dump complete.

Ответы [ 7 ]

7 голосов
/ 25 августа 2010

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

Чтобы понять их преимущества и недостатки, мы должны понимать различные механизмы и требования:

  1. Как новые, удалить, malloc и free перехватили?Некоторые инструменты используют #define для переопределения new, delete, malloc и free, но это зависит от правильного порядка включаемых файлов и может создавать проблемы, если класс содержит, например, метод с именем free (как в случае с Qt).Препроцессор также переопределит этот метод, что может привести к ошибкам компиляции или неразрешенным внешним проблемам.

    Другой способ - отменить глобальные операторы new и delete.Это намного более чистое решение, но оно не работает, если у вас есть сторонняя библиотека, которая помещает новую в библиотеку, но удаляет ее в заголовке (или наоборот).

  2. Как этоисточник звонка определен.Если new, delete, ... перехватываются с помощью # define, часто символы препроцессора __FILE__ и __LINE__ используются для получения источника утечки.Однако, если в вашем коде есть «универсальные» функции, такие как, например, CreateString (), то большая часть утечек будет сообщаться в этих универсальных функциях, что на самом деле вам не поможет.

    Альтернативой является получениестек вызовов во время выполнения.Это легко сделать с помощью функции Windows StackWalk, но, по моему опыту, это очень и очень медленно.Гораздо более быстрой альтернативой является непосредственное получение базового указателя и использование указателей стека-фрейма (вы должны скомпилировать с помощью / Oy-, чтобы получить указатели стека-фрейма).Вы можете получить указатель кадра (базы) следующим образом: _asm mov DWORD PTR [FramePtr], ebp.Затем просто зациклите, и в цикле получите указатель инструкции от ((ADDR *)FramePtr)[1]; и следующий указатель кадра от FramePtr = ((ADDR *)FramePtr)[0];

  3. Как сообщить об утечках в точный момент.В моем случае я хочу, чтобы об утечках сообщалось в конце приложения, но для того, чтобы сделать это, вам нужен механизм сообщения об утечках в конце приложения.Это означает, что если вы хотите сообщить о своих утечках самостоятельно, вам нужно полагаться на уничтожение глобальных переменных в конце вашего приложения (и сообщать об утечках в этом деструкторе глобальной переменной).Для приложений серверного типа вы, вероятно, больше заинтересованы в получении разницы в использовании памяти между двумя точками во времени.

А теперь разные системы утечки:

  1. C RunTime: сообщает об утечках в конце, но не имеет достойного способа сообщения стеков вызовов.Его метод перехвата вызовов new, delete, ... может вызывать проблемы в комбинациях со сторонними библиотеками (такими как Qt, Boost, ...)

  2. Внешние утилиты Microsoft (например, GFlags), UMDH ,, ...): кажется, что они могут регистрировать различия только между двумя моментами времени.Тем не менее, стек вызовов выглядит намного лучше, хотя утилита GFlags может устанавливать флаги в ОС, которые могут вызвать серьезное замедление работы вашего приложения.

  3. Visual Leak Detector.Кажется, правильно находит все утечки, но в моем случае это не работает, так как у меня есть сторонняя DLL, которая просто прерывает процесс при его DllUnload (кажется, это специфическая проблема Windows 7).

  4. Мой личный фаворит (и люди не согласятся со мной, я уверен), это написать свой собственный менеджер памяти.Перехват может быть легко осуществлен с использованием глобальных операторов new и delete (с возможными проблемами, упомянутыми выше), и вы можете получить стек вызовов, как описано выше.Эта альтернатива также основана на возможности иметь код, который выполняется в самый последний момент в вашем приложении.

При выборе альтернативы я обнаружил, что следующие аспекты очень важны для моей ситуации:

  • Я хочу, чтобы это работало без проблем в моем приложении, чтобы каждый разработчик был немедленно уведомлен в случае утечки.Если вы отложите проверку на утечку на более поздний момент, когда будете использовать внешние утилиты, такие как Purify, обнаружение утечки будет намного сложнее.
  • Я хочу, чтобы в конце приложения автоматически сообщалось об утечках.
  • Мне нужно как можно больше информации от утечки (данные, стек вызовов, ...)

Надеюсь, это поможет.

5 голосов
/ 25 августа 2010

Это выходные данные отладочной CRT Visual Studio, а не выходные данные Visual Leak Detector.Во-первых, убедитесь, что вы используете текущую версию Codeplex и что у вас есть #included vld.h в вашем проекте.Вы получите намного более информативный вывод.

2 голосов
/ 25 августа 2010

Я получил его после отладки большого количества заголовочных файлов.

Вот что нужно сделать, чтобы включить номер файла / строки в выводе

#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
1 голос
/ 25 августа 2010

Скомпилировали ли вы с включенной отладочной информацией и убедитесь, что pdb-файл доступен детектором утечек?Без этой информации он не сможет предоставить номера строк.

0 голосов
/ 25 августа 2010

Если номера присвоения (те, что указаны в фигурных скобках) всегда одинаковы, это может помочь . В основном, это описывало, как заставить VC ++ генерировать точку останова при попытке выделения с указанным номером.

0 голосов
/ 25 августа 2010

Rational Purify доступен в качестве плагина для VC ++ и предназначен для обнаружения утечек (и других проблем). Я часто использовал его в Solaris, и он был очень простым в использовании и понятным. Я также слышал хорошие отзывы от других людей о версии для использования с Visual Studio, но на самом деле я никогда не пробовал это.

FWIW, я подозреваю, что Purify был вдохновением для Valgrind, о котором уже упоминалось.

0 голосов
/ 25 августа 2010

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

...