Обнаружение утечки памяти при выполнении юнит-тестов - PullRequest
4 голосов
/ 04 октября 2008

У меня есть приложение Win32 C ++ с набором модульных тестов. После завершения модульных тестов я бы хотел, чтобы читаемый человеком отчет о любой неосвобожденной памяти создавался автоматически. В идеале отчет должен иметь стек с файлами и информацией о номере строки для каждого несвободного размещения. Было бы неплохо, чтобы они были сгенерированы в последовательном порядке, чтобы облегчить их преобразование из одного цикла в другой. (В основном, я хотел бы, чтобы результаты valgrind --leak-check = full, но на окнах).

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

Есть ли инструмент, который может это сделать? Если да, то как мне его использовать?

Спасибо!

Ответы [ 5 ]

4 голосов
/ 04 октября 2008

Чтобы получить такую ​​информацию, мы переопределяем new / delete и malloc / free, предоставляя наши собственные реализации кучи, которые хранят трассировки стека при распределении и генерируют отчет об уничтожении кучи (а также добавляем часовые для обнаружения переполнения буфера) .

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

1 голос
/ 04 октября 2008

Если вы используете MSVC, можно использовать функции кучи отладки Microsoft для создания необходимого отчета, но он может быть не таким автоматическим, как вам хотелось бы (вам может понадобиться написать некоторый пользовательский код):

_CrtSetReportMode
_CrtSetReportFile
_CrtMemState    
_CrtMemCheckpoint
_CrtMemDumpStatistics
_CrtSetReportFile
_CrtSetDbgFlag
0 голосов
/ 05 октября 2008

Я поиграл с функциями CRT Debug Heap, на которые указал Майк Б., но в конечном итоге я не был удовлетворен, просто получив адрес утечки памяти. Получение стеков, подобных UMDH, значительно ускоряет отладку. Итак, в моей функции main () теперь я Запустите UMDH с помощью CreateProcess до и после запуска тестов для создания снимков кучи. Я также написал тривиальный пакетный файл, который запускает мой тестовый жгут, а затем показывает снимки кучи. Итак, я запускаю командный файл и получаю результаты своих тестов и текстовый файл с полными стеками всех несвободных выделений в одном кадре.

UMDH обнаруживает много ложных срабатываний, так что, возможно, какое-то гибридное из CrtDebug и то, что я делаю сейчас, было бы лучшим решением. Но сейчас я доволен тем, что у меня есть.

Теперь, если бы у меня был способ определить, не закрывал ли я какие-либо ручки ...

0 голосов
/ 04 октября 2008

Я делал это один раз, но это было не так автоматически. У меня нет доступа к этому коду сейчас, но вот идея:

Я использовал функции отладки , о которых упоминал Майк Б. (кстати, они работают только в режиме отладки).

Выполнитель тестов выполнил все тесты дважды, поскольку во время первого запуска память выделяется для глобальных переменных. Во второй раз общее количество выделенных блоков проверялось до и после каждого теста (я думаю, вы можете сделать это в setUp () и tearDown ()). Если число было другим, это означало утечку памяти, и тест не удался с соответствующим сообщением. Конечно, если сам тест не пройден, вы должны сохранить его сообщение об ошибке. Теперь, чтобы найти утечку, мне пришлось прочитать номер выделения блока последнего выделения с помощью pBlockHeader, затем установить точку останова на нем с помощью _CrtSetBreakAlloc и запустить снова.

Подробнее об этом здесь: http://levsblog.wordpress.com/2008/10/31/unit-testing-memory-leaks/

0 голосов
/ 04 октября 2008

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

Подробнее здесь:

http://msdn.microsoft.com/en-us/library/tz7sxz99(VS.80).aspx

...