什么是內存泄漏?
內存泄漏(memory leak),指由於疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏並非指內存在物理上的消失,而是應用程序分配某段內存后,由於設計錯誤,失去了對該段內存的控制,因而造成了內存的浪費。
C和C++內存泄露
對於C和C++這種沒有Garbage Collection 的語言來講,我們主要關注兩種類型的內存泄漏:
堆內存泄漏(Heap leak)。對內存指的是程序運行中根據需要通過malloc,realloc, new等從堆中分配的一塊內存,完成后必須通過調用對應的 free或者delete 釋放掉。如果程序設計的錯誤導致這部分內存沒有被釋放,那么此后這塊內存將不會被使用,就會產生Heap Leak.
系統資源泄露(Resource Leak)。主要指程序使用系統分配的資源比如 Bitmap,Handle,SOCKET等沒有使用相應的函數釋放掉,導致系統資源的浪費,嚴重可導致系統效能降低,系統運行不穩定。
如何解決內存泄露?
內存泄露的問題其困難在於:
1、編譯器不能發現這些問題。
2、運行時才能捕獲到這些錯誤,這些錯誤沒有明顯的症狀,時隱時現。
3、對於手機等終端開發用戶來說,尤為困難。
下面從三個方面來解決內存泄露:
第一,良好的編碼習慣,盡量在涉及內存的程序段,檢測出內存泄露。當程序穩定之后,再來檢測內存泄露時,無疑增加了排除的難度和復雜度。
使用了內存分配的函數,要記得要使用其釋放函數釋放掉。
Heap memory:
malloc\realloc ------ free
new \new[] ---------- delete \delete[]
GlobalAlloc------------GlobalFree
Resource Leak :
對於系統資源使用之前要仔細看其使用說明,防止錯誤使用或者忘記釋放掉系統資源。
對於基於引用計數的系統對象尤其要注意,因為只有其引用計數為0時,該對象才能正確被刪除。而其使用過程中又生成的新的系統資源,使用完畢后,如果沒有及時刪除,都會影響其引用計數。
使用Visual Leak Detector for Visual C++
簡介
Visual Leak Detector是一款免費的、健全的、開源的Visual C++內存泄露檢測系統。相比Visual C++自帶的內存檢測機制,Visual Leak Detector可以顯示導致內存泄露的完整內存分配調用堆棧。
使用方法
VLD簡單易用,文檔也很豐富,對於內存泄露的具體位置也能以調用堆棧的形式詳細的顯示出來。
下載安裝后,僅僅需要告訴Visual C++在哪里找到include文件和lib文件。
C/C++ -> General -> Additional Include Directories = C:\Program Files (x86)\Visual Leak Detector\include
Linker -> General -> Additional Library Directories = C:\Program Files (x86)\Visual Leak Detector\lib\Win32
Linker -> Input-> Additional Dependencies = vld.lib
然后,在代碼上的變動就只需要簡單的加上#include <vld.h> 就可以了。
當你在Visual C++中調試運行你的程序時,在程序結束后VLD將在output窗口輸出一個內存泄露報告,該報告包括了你的程序中內存分配的完成調用棧信息。雙擊調用棧的某一行,就可以迅速跳轉到你的代碼編輯器相應的位置。
Visual Leak Detector有一些配置項,可以設置內存泄露報告的保存地(文件、調試器),拷貝"\Visual Leak Detector"路徑下的vld.ini文件到工程的Debug目錄下(在IDE運行的話,則需要拷貝到工程目錄下),修改以下項:
ReportFile = .\memory_leak_report.txt
ReportTo = both
可以看到在Debug目錄下生成文件memory_leak_report.txt,跟VS中Output窗口輸出的內容一樣。
總之,VLD是一種高效的診斷、修復C/C++程序內存泄露的方法。
應用舉例
#include "stdafx.h" #ifdef _DEBUG //在Release模式下,不會鏈接Visual Leak Detector #include "vld.h" #endif int _tmain(int argc, _TCHAR* argv[]) { char* ch1 = new char[100]; char* ch2 = (char*)malloc(200); /* if (ch1 != NULL) { delete[] ch1; ch1 = NULL; } if (ch2 != NULL) { free(ch2); ch1 = NULL; } */ return 0; }
Output輸出:
Visual Leak Detector Version 2.2.3 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 1 at 0x008CD6F8: 100 bytes ----------
Call Stack:
c:\users \consoleapplication\consoleapplication.cpp (12): ConsoleApplication.exe!wmain + 0x7 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (533): ConsoleApplication.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (377): ConsoleApplication.exe!wmainCRTStartup
0x74EE8543 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x770EAC69 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x85 bytes
0x770EAC3C (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x58 bytes
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 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 ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD ........ ........
---------- Block 2 at 0x008CD798: 200 bytes ----------
Call Stack:
c:\users\ \consoleapplication\consoleapplication.cpp (13): ConsoleApplication.exe!wmain + 0xD bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (533): ConsoleApplication.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (377): ConsoleApplication.exe!wmainCRTStartup
0x74EE8543 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x770EAC69 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x85 bytes
0x770EAC3C (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x58 bytes
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 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 ........ ........
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 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 ........ ........
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 (372 bytes).
Largest number used: 372 bytes.
Total allocations: 372 bytes.
Visual Leak Detector is now exiting.
The program '[0x262C] ConsoleApplication1.exe' has exited with code 0 (0x0).
輸出的部分主要分為兩塊
Call Stack部分:
是泄露內存的調用堆棧,其中顯示了泄露資源創建的位置,雙擊便可以定位到相應的代碼部分。
Data部分:
即泄露部分的內存內容。
