剛接觸C++的時候總感覺內存洩露是很可怕的事,覺得手足無措,直到有一天發現心裡的巨石居然是那麼小的一個case。
方法一:利用CRT調試堆函數
舉例說明:
#ifdef _DEBUG
#define CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
int main()
{
char *p = new char[200];
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_REPORT_FLAG | _CRTDBG_LEAK_CHECK_DF);
#endif
return 0;
}
輸出信息:
Detected memory leaks!
Dumping objects ->
f:\test\highquality\c++primer\main.cpp(10) : {69} normal block at 0x00396990, 200 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
分析:
{xxx} — 表示程序運行後第xxx次內存分配發生了洩漏,即內存分配編號;
xxx block — 表示內存塊類型,包括三種:普通(normal)、客戶端(client)和運行時(CRT);
at 0x00396990 — 表示發生洩漏的內存地址,用十六進制表示;
xx bytes long — 表示發生洩漏的內存大小;
Data:xxx — 表示內存數據信息,一般輸出前16字節的內容。
利用_CrtSetBreakAlloc()設置分配指定的內存時,中斷,然後查看調用棧。
#ifdef _DEBUG
#define CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
int main()
{
_CrtSetBreakAlloc(69);
char *p = new char[200];
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_REPORT_FLAG | _CRTDBG_LEAK_CHECK_DF);
#endif
return 0;
}
方法二:使用VLD工具
Visual Leak Detector是一款用於Visual C++的免費的內存洩露檢測工具。相比較其它的內存洩露檢測工具,它在檢測到內存洩漏的同時,具有如下特點:
(1).可以得到內存洩漏點的調用堆棧,如果可以的話,還可以得到其所在文件及行號;
(2).可以得到洩露內存的完整數據;
(3).可以設置內存洩露報告的級別;
(4).它是一個已經打包的lib,使用時無須編譯它的源代碼。而對於使用者自己的代碼,也只需要做很小的改動;
(5).他的源代碼使用GNU許可發布,並有詳盡的文檔及注釋。對於想深入了解堆內存管理的讀者,是一個不錯的選擇。
1.下載VLD工具 http://www.codeproject.com/tools/visualleakdetector.asp
2.使用 解壓之後得到vld.h, vldapi.h, vld.lib, vldmt.lib, vldmtdll.lib, dbghelp.dll等文件。將.h文件和.lib文件拷貝到你要檢測的工程文件所在的目錄裡(只針對此工程),將dbghelp.dll拷貝到你的程序的運行目錄下。
3.用法:在包含入口函數的.cpp文件中加入語句#include "vld.h"即可。
編譯正確後,在debug方式下運行:查看VC的輸出信息:
有內存洩露顯示:"WARNING: Visual Leak Detector detected memory leaks!"
沒有內存洩露,此輸出的信息為:"No memory leaks detected."
4.舉例說明:
#include <iostream>
#include <string>
#include "vld.h"
using namespace std;
int main()
{
int *n = new int[10];
string *s = new string("hello!\n");
cout << n;
cout << *s;
return 0;
}
輸出信息中包含以下語句:
Visual Leak Detector Version 1.0 installed (multithreaded static).
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 84 at 0x003E6CB8: 32 bytes ----------
Call Stack:
f:\test\highquality\c++primer\main.cpp (10): main
f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (327): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (196): mainCRTStartup
0x7C817077 (File and line number not available): RegisterWaitForInputIdle
Data:
00 00 00 00 CD CD CD CD 68 65 6C 6C 6F 21 0A 00 ........ hello!..
CD CD CD CD CD CD CD CD 07 00 00 00 0F 00 00 00 ........ ........
---------- Block 83 at 0x003E6C50: 40 bytes ----------
Call Stack:
f:\dd\vctools\crt_bld\self_x86\crt\src\newaop.cpp (7): operator new[]
f:\test\highquality\c++primer\main.cpp (9): main
f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (327): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (196): mainCRTStartup
0x7C817077 (File and line number not available): RegisterWaitForInputIdle
Data:
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD ........ ........
Visual Leak Detector detected 2 memory leaks.
“C++primer.exe”: 已卸載“C:\WINDOWS\system32\dbghelp.dll”
“C++primer.exe”: 已卸載“C:\WINDOWS\system32\version.dll”
Visual Leak Detector is now exiting.
程序“[1740] C++primer.exe: 本機”已退出,返回值為 0 (0x0)。
代碼改為:
#include <iostream>
#include <string>
#include "vld.h"
using namespace std;
int main()
{
int *n = new int[10];
string *s = new string("hello!\n");
cout << n;
cout << *s;
delete [] n;
delete s;
return 0;
}
輸出信息中包含以下語句:
Visual Leak Detector Version 1.0 installed (multithreaded static).
No memory leaks detected.
“C++primer.exe”: 已卸載“C:\WINDOWS\system32\dbghelp.dll”
“C++primer.exe”: 已卸載“C:\WINDOWS\system32\version.dll”
Visual Leak Detector is now exiting.
程序“[4272] C++primer.exe: 本機”已退出,返回值為 0 (0x0)。
作者:one_in_one