Как использовать Application Verifier для обнаружения утечек памяти - PullRequest
9 голосов
/ 02 июня 2010

Я хочу найти утечки памяти в моем приложении, используя стандартные утилиты. Ранее я использовал свой собственный распределитель памяти, но другие люди (да, вы AlienFluid) предлагали использовать Microsoft Application Verifier, но я не могу заставить его сообщать о моих утечках. У меня есть следующее простое приложение:

#include <iostream>
#include <conio.h>

class X
   {
   public:
      X::X() : m_value(123) {}
   private:
      int m_value;
   };

void main()
{
X *p1 = 0;
X *p2 = 0;
X *p3 = 0;

p1 = new X();
p2 = new X();
p3 = new X();
delete p1;
delete p3;
}

Этот тест явно содержит утечку памяти: p2 новый, но не удален.

Я строю исполняемый файл, используя следующие командные строки:

cl /c /EHsc /Zi /Od /MDd test.cpp
link /debug test.obj

Я скачал Application Verifier (4.0.0665) и включил все проверки.

Если я сейчас запускаю тестовое приложение, я вижу его журнал в Application Verifier, но не вижу утечки памяти.

Вопросы:

  • Почему Application Verifier не сообщает об утечке?
  • Или Application Verifier действительно не предназначен для обнаружения утечек?
  • Если нет других доступных инструментов, позволяющих четко сообщать об утечках в конце приложения (т.е. не делать регулярные снимки и сравнивать их, поскольку это невозможно в приложении, занимающем 1 ГБ или более), включая вызов стек места размещения (поэтому не простое сообщение об утечке в конце CRT)

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

Ответы [ 6 ]

4 голосов
/ 04 мая 2011

Application Verifier только улавливает утечки в DLL. Попробуйте прочитать подсказку в флажке утечки. Вот что он говорит.

4 голосов
/ 02 июня 2010

Обнаружение утечек памяти ЭЛТ (без трассировки стека):

// debug_new.h
#pragma once

#include "crtdbg.h"

#ifdef _DEBUG
#ifndef DEBUG_NEW
#define DEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#endif

Все файлы .cpp:

#include "debug_new.h"

...

// After all other include lines:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

...

Запишите это один раз в код инициализации программы:

_CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

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

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

Ограничения: при этом обнаруживаются только "новые" утечки памяти, все утечки, вызванные другими функциями, такими как malloc, не обнаруживаются.

Не делайте никаких выделений внутри файлов .h - они будут напечатаны без исходных строк, поскольку DEBUG_NEW определяется после всех строк #include.

1 голос
/ 18 июня 2012

Memory Validator из Software Verification будет обнаруживать утечки памяти и отображать полный стек вызовов из распределения утечек.Хотя это коммерческий продукт, у него есть пробный период, поэтому программисты могут попробовать его и посмотреть, стоит ли он им цены.

1 голос
/ 04 июня 2010

У меня такое ощущение, что Application Verifier в особых случаях указывает путь выхода и не помечает их как утечки - в конце концов, вся куча процесса свободна при выходе из процесса.

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

Кроме того, AppVerifier (если у вас включены все опции) также должен перехватывать переполнения буфера, переполнения, записи в ячейки стека, помеченные как RO и т. Д.

0 голосов
/ 28 октября 2011

Визуальный детектор утечек (v2.2) более полезен, чем библиотека отладки CRT, поскольку он покажет, что полный стек вызовов, использованный для выделения памяти, привел к утечке.

0 голосов
/ 02 июня 2010

Самое простое решение - не записывать утечки или переполнения буфера в первую очередь - их обнаружение после события действительно является пустой тратой усилий. В моем собственном коде в течение многих лет у меня не было проблем в этих областях. Зачем? Потому что я использую механизмы, которые предоставляет C ++, чтобы избежать их. Например:

X *p1 = 0;
p1 = new X();

должно быть:

shared_ptr <X>  p1 = new X();

и вы больше не беспокоитесь о утечке p1. Более того, вообще не используйте динамическое распределение:

X x1;

Для переполнения буфера всегда используйте типы, такие как std :: string, которые будут увеличиваться при вводе, или, если они не растут, обнаружат возможное переполнение и предупредят вас.

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

...