Я хочу найти утечки памяти в своем приложении с помощью стандартных утилит. Ранее я использовал свое собственное средство выделения памяти, но другие люди (да, Вы AlienFluid) предложили использовать Верификатор Приложения Microsoft, но я, может казаться, не заставляю это сообщать о моих утечках. У меня есть следующее простое приложение:
#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 является new'd, но не удаленный.
Я создаю исполняемый файл с помощью следующих командных строк:
cl /c /EHsc /Zi /Od /MDd test.cpp
link /debug test.obj
Я загрузил Верификатор Приложения (4.0.0665) и включил все проверки.
Если я теперь работаю, мое тестовое приложение I видит журнал его в Верификаторе Приложения, но я не вижу утечку памяти.
Вопросы:
Если я не нахожу достойную утилиту, я все еще должен полагаться на своего собственного диспетчера памяти (который делает это отлично).
Обнаружение утечек памяти CRT (без трассировки стека):
// 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.
У меня такое ощущение, что Application Verifier специально рассматривает путь выхода и не отмечает эти утечки как утечки - в конце концов, вся куча процесса освобождается при его выходе.
Попробуйте написать другой пример, где вы снова инициализируете тот же указатель - по сути, теряете ссылку на предыдущее выделение. Это, конечно, должно быть отмечено. Сообщите мне о результатах.
Кроме того, AppVerifier (если у вас включены все опции) должен также отлавливать переполнения буфера, недополнения, запись в места стека, помеченные RO и т.д.
Простейшим решением является не записывать утечки или переполнения буфера в первую очередь - обнаружение их после события действительно является пустой тратой усилий. В моем собственном коде в течение многих лет у меня не было проблем в этих областях. Почему? Потому что я использую механизмы, которые предоставляет C ++, чтобы их избежать. Например:
X *p1 = 0;
p1 = new X();
должно быть:
shared_ptr <X> p1 = new X();
, и вы больше не беспокоитесь об утечке p1. Еще лучше вообще не использовать динамическое распределение:
X x1;
Для переполнения буфера всегда используйте такие типы, как std :: string, которые будут увеличиваться при вводе, или, если они не увеличиваются, обнаружат возможное переполнение и предупредит вас.
Я не хвастаюсь своим умением избегать утечек памяти - это действительно работает и позволяет вам справляться с гораздо более сложной задачей отладки бизнес-логики вашего кода.