c/c++使用 CRT 庫查找內存泄漏
前言:
內存泄漏,即未能正確釋放以前分配的內存,是 C/C++ 應用程序中最難以捉摸也最難以檢測到的 Bug 之一。 最初少量內存泄漏可能不引人註目,但隨著時間的推移,內存泄漏越來越多,就會出現一些征兆,包括性能下降,在應用程序內存不足時發生崩潰。 更嚴重的是,占用了所有可用內存的泄漏應用程序可能會導致其他應用程序崩潰,從而無法確定問題出在哪個應用程序。 即使看似無害的內存泄漏也可能說明存在其他問題應當糾正。
借助 Visual Studio 調試器和 C 運行時 (CRT) 庫,可以檢測和識別內存泄漏。
啟動內存泄漏檢測:
檢測內存泄漏的主要工具是調試器和 C 運行庫 (CRT) 調試堆函數。
若要啟用調試堆函數,請在程序開頭包括以下語句:
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h>
且引用順序不能改變!!
使用這些語句啟用調試堆函數之後,可以在某個應用程序退出點之前設置一個對 _CrtDumpMemoryLeaks
的調用,以便在應用程序退出時顯示內存泄漏報告:
_CrtDumpMemoryLeaks();
如果應用程序有多個退出點,並不需要在每個退出點都手動設置一個對 _CrtDumpMemoryLeaks 的調用。 main函數開頭部分對 _CrtSetDbgFlag
_CrtDumpMemoryLeaks
。 你必須設置兩個位域,如下所示:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
默認情況下,_CrtDumpMemoryLeaks
將內存泄漏報告輸出到“輸出”窗口的“調試”窗格中。 你可以使用 _CrtSetReportMode
將該報告重定向到其他位置。
如果使用庫,該庫可能會將輸出重置到另一位置。 在此情況下,可以將輸出位置設置回“輸出”窗口,如下所示:
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
實例:
1 #define _CRTDBG_MAP_ALLOC 2 #include <stdlib.h> 3 #include <crtdbg.h> //為了 CRT 函數能夠正常工作,#include 語句必須遵循此處所示的順序 4 #include <stdio.h> 5 6 int main() { 7 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 8 char*a = NULL;//聲明一個char*類型的指針 9 10 a = (char*)malloc( sizeof(char)*100); //使用malloc分配內存的首地址,然後賦值給a 11 12 if (!a) 13 14 { 15 perror("malloc"); 16 return-1; 17 } 18 19 sprintf(a, "%s", "Hello World\n"); //"HelloWorld\n"寫入a指向的地址 20 21 printf("%s\n", a); //輸出用戶輸入的數據 22 23 //free(a); //釋放掉使用的內存地址 24 system("pause"); 25 return 0; 26 } 27
為了測試,我們將free(a)註釋掉,得到的結果如下:
Detected memory leaks! Dumping objects -> d:\c++lianxi\c++items\neicun\neicun\test.cpp(10) : {81} normal block at 0x002DC1E0, 100 bytes long. Data: <Hello World > 48 65 6C 6C 6F 20 20 57 6F 72 6C 64 0A 00 CD CD Object dump complete.
-
內存分配編號,在本例中為 81
-
塊類型,在本例中為
normal
。 -
十六進制內存位置,在本例中為0x002DC1E0。
-
塊的大小,在本例中為 100
bytes
。 -
塊中前 16 個字節的數據(十六進制形式)
如果應用程序未定義 _CRTDBG_MAP_ALLOC
,則 _CrtDumpMemoryLeaks 顯示的內存泄漏報告如下所示:
Detected memory leaks! Dumping objects -> {18} normal block at 0x00780E80, 64 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD Object dump complete.
區別在於,第一份報告顯示文件名,以及泄漏的內存初次分配所在位置的行號。
不論是否定義 _CRTDBG_MAP_ALLOC
,內存泄漏報告都顯示上面的信息。
c/c++使用 CRT 庫查找內存泄漏