Я использовал визуальный детектор утечки с вполне положительными результатами. Это небольшое и аккуратное, и может быть встроено в ваш проект (если у вас есть текущая конфигурация Debug) в считанных секундах:
https://vld.codeplex.com/
Если правильно установить вверх (что может быть сделано с помощью программы установки), то у вас есть только
#include <vld.h>
в одной ваших файлов .cpp для каждого модуля - это его заголовок будет делать увязку для вас. Вам не нужно класть его повсюду. Внутри инструмент использует CrtDbg, поэтому для его работы необходимо иметь отладочную сборку.
Он дает вам отладчик или текстовый вывод после каждого запуска (если он настроен с использованием файла конфигурации), даже если он не запускается через отладчик. Это не самый мощный инструмент, но они обычно стоят немного денег;)
EDIT: Существует возможность включения VLD также в неотладочных конфигурациях путем определения VLD_FORCE_ENABLE
перед включением заголовка. Но тогда результаты могут быть смягчены.
EDIT: Я попробовал свежую установку VLD. Обратите внимание, что для компиляторов VS2013 необходимо использовать версию v2.4rc2 (или что-то большее v2.3). Версия v2.3 работает только до компиляторов VS2010.
После установки я создал новый проект и установил свои каталоги включений и библиотек, чтобы включить соответствующие папки VLD. После этого я использовал следующий код для проверки memleak отчеты одиночек (обратите внимание, что этот код не имеет смысла, это только доказывает точку):
#include <iostream>
#include <string>
#include <sstream>
#include <map>
// Uncomment this, if you want VLD to work in non-debug configurations
//#define VLD_FORCE_ENABLE
#include <vld.h>
class FooSingleton {
private:
std::map<std::string, std::string*>
_map;
FooSingleton() {
}
public:
static FooSingleton* getInstance(void) {
/* THIS WOULD CAUSE LEAKS TO BE DETECTED
SINCE THE DESTRUCTOR WILL NEVER BE CALLEd
AND THE MAP IS NOT CLEARED.
*/
// FooSingleton* instance = new FooSingleton;
// return instance;
static FooSingleton instance;
return &instance;
}
void addString(const std::string& val) {
_map.insert(std::make_pair(val, new std::string(val)));
}
~FooSingleton(void) {
auto it = _map.begin();
auto ite = _map.end();
for(; it != ite; ++it) {
delete it->second;
}
}
};
int main(int argc, char** argv) {
FooSingleton* fs = FooSingleton::getInstance();
for(int i = 0; i < 100; ++i) {
std::stringstream ss;
ss << i << "nth string.";
fs->addString(ss.str());
}
return 0;
}
С помощью этого кода, то VLD не сообщать о любых утечек, потому что статическая автоматическая переменная в getInstance()
будет уничтожена после выхода, а элементы на карте будут удалены. Это должно быть сделано, тем не менее, даже если это синглтон, иначе будут сообщены утечки.Но в этом случае:
Visual Leak Detector Version 2.3 installed.
Aggregating duplicate leaks.
Outputting the report to the debugger and to D:\dev\projects\tmp\memleak\memleak\memory_leak_report.txt
No memory leaks detected. Visual Leak Detector is now exiting.
Если код в getInstance()
изменяется на закомментированное версии, то одноплодный никогда не прояснились, и следующие утечки (среди прочих) сообщаются:
---------- Block 11 at 0x008E5928: 52 bytes ----------
Leak Hash: 0x973608A9 Count: 100
Call Stack:
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (36): memleak.exe!std::_Allocate<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0x15 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (187): memleak.exe!std::allocator<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0xB bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (560): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0xD bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (588): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0x8 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (756): memleak.exe!std::_Tree<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std:: + 0x17 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (33): memleak.exe!FooSingleton::addString + 0xA9 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (51): memleak.exe!main + 0x37 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): memleak.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): memleak.exe!mainCRTStartup
0x76BF919F (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x7739A22B (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x84 bytes
0x7739A201 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
Data:
C0 53 8E 00 30 67 8E 00 C0 53 8E 00 98 58 8E 00 .S..0g.. .S...X..
30 6E 74 68 20 73 74 72 69 6E 67 2E 00 CD CD CD 0nth.str ing.....
0C 00 00 00 0F 00 00 00 CD CD CD CD 48 56 8E 00 ........ ....HV..
01 00 CD CD
Вы можете четко видеть Count: 100
для этого блока кода, что является правильным.
Я также отредактировал мой vld.ini
файл в каталоге установки, чтобы иметь следующий набор должен быть включен:
AggregateDuplicates = yes
ReportTo = both
Они убедитесь, что а) все повторяющиеся утечки раздавлены вместе один отчет с утечкой подсчета (как указано выше, иначе будет 100 записей), а другой, чтобы файл отчета был сброшен в каталог приложения.
Таким образом, для одиночных игр он работает нормально, если вы используете подход статической автоматической переменной, который вы используете, и выполняете очистку в деструкторе.
EDIT: Кроме того, прибор может быть отключен на определенных частях кода. Если приведенный выше код будет изменен следующим образом:
void addString(const std::string& val) {
VLDDisable();
_map.insert(std::make_pair(val, new std::string(val)));
VLDEnable();
}
Утечки не никогда профилировать и не отслеживаются.
Есть инструменты, которые не являются бесплатными, но обеспечивают полнофункциональную пробную версию. Поэтому вам не нужно тратить свои деньги, чтобы проверить утечки. –
Не совсем уверен, что это именно то, что вам нужно, но valgrind http://valgrind.org/docs/manual/mc-manual.html предоставляет инструменты для устранения утечки памяти. – Vincent