剛接觸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
http://www.2cto.com/kf/201207/140707.html