.1. VS 2008 中記憶體泄露檢查
檢測記憶體流失的主要工具是調試器和 CRT 調試堆函數。若要啟用調試堆函數,請在程式中包括以下語句:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
a) 通過包括 crtdbg.h,將 malloc 和 free 函數映射到其“Debug”版本_malloc_dbg 和_free_dbg,這些函數將跟蹤記憶體配置和釋放。此映射只在調試版本(在其中定義了 _DEBUG)中發生。發布版本使用普通的 malloc 和 free 函數
b) #define _CRTDBG_MAP_ALLOC語句將 CRT 堆函數的基版本映射到對應的“Debug”版本。並非絕對需要該語句,但如果沒有該語句,記憶體流失轉儲包含的有用資訊將較少。
c) 在添加了上面所示語句之後,可以通過在程式中包括以下語句來轉儲記憶體流失資訊:
_CrtDumpMemoryLeaks();
當在調試器下運行程式時,_CrtDumpMemoryLeaks 將在“輸出”視窗中顯示記憶體流失資訊。記憶體流失資訊如下所示:
Detected memory leaks!
Dumpingobjects ->
X:XX.cpp(172): {1875} normal block at 0x00780E80, 78600 bytes long.//記憶體配置編號, 塊類型(普通、用戶端或CRT),記憶體位置,塊大小
Data: <> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD//前 16 位元組內容(十六進位)
Object dumpcomplete.
----如果程式可以從多個位置退出,在程式開始包括以下調用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF |_CRTDBG_LEAK_CHECK_DF );
該語句在程式退出時自動調用 _CrtDumpMemoryLeaks。必須同時設定 _CRTDBG_ALLOC_MEM_DF 和 _CRTDBG_LEAK_CHECK_DF 兩個位域,如上所示。
----確定記憶體泄露位置
添加如下一行(對於第 1875 個記憶體配置):
_crtBreakAlloc = 1875;//第1875次申請記憶體配置時
或者,可以使用具有同樣效果的 _CrtSetBreakAlloc 函數:
_CrtSetBreakAlloc(1875);
在調試狀態下運行序,在斷點停下時,開啟“呼叫堆疊”視窗,找到對應的原始碼處;
退出程式,觀察“輸出視窗”的記憶體泄露報告,看實際記憶體配置的塊號是不是和預設值相同,如果相同,就找到了;如果不同,就重複步驟3,直到相同。
(來源:http://blog.sina.com.cn/s/blog_4bf793ad0100jsxy.html)
2. 記憶體泄露的解決方案
Smartpointer ----STL中已經廣泛應用
Garbadgecollection ----java
3. 記憶體泄露一般指堆記憶體泄露
Malloc、realloc、new三種方式申請堆記憶體
釋放方式為: free、delete
4. 系統資源的泄漏(resource leak)
核心態HANDLE,GDIObject,SOCKET,Interface等,從根本上說這些由作業系統分配的對象也消耗記憶體,如果這些對象發生泄漏最終也會導致記憶體的泄漏
5. 如果要檢測堆記憶體的泄漏,那麼需要截獲住 malloc/realloc/free和new/delete就可以了(其實new/delete最終也是用malloc/free的,所以只要截獲前面一組即可)。對於其他的泄漏,可以採用類似的方法,截獲住相應的分配和釋放函數。比如,要檢測BSTR的泄漏,就需要截獲
SysAllocString/SysFreeString;要檢測HMENU的泄漏,就需要截獲CreateMenu/ DestroyMenu
6.windows平台記憶體泄露偵查工具:
MSC-Runtime Library 內建檢測功能;
第三方(外掛式)偵查工具:Purify,boundschecker;
Windows內建的performancemonitor
7. BoundsChecker
採用一種被稱為 Code Injection的技術,來截獲對分配記憶體和釋放記憶體的函數的調用。簡單地說,當你的程式開始運行時,BoundsChecker的DLL被自動載入進程的地址空間(這可以通過system-level的Hook實現),然後它會修改進程中對記憶體配置和釋放的函數調用,讓這些調用首先轉入它的代碼,然後再執行原來的代碼。BoundsChecker在做這些動作的時,無須修改被偵錯工具的原始碼或工程設定檔,這使得使用它非常的簡便、直接。
8.基類解構函式應聲明為virtual
RAIIà建構函式中申請資源,解構函式中釋放資源。例如:STL中的auto_ptr
9. 編碼規範檢查工具 CodeWizard
內建500多條編碼規則,可隨意組合
與vs c++無縫整合
10. 代碼檢查工具 PC-Lint
PC-Lint可檢查編譯器不易發現的錯誤。PC-Lint可對100多個C庫函數進行檢查,可以發現標準C/C++代碼中的1 000多個常見錯誤。
11. 利用Purify和Insure++尋找運行時記憶體缺陷
Rational Purify和Parasoft Insure++ 是用於執行階段錯誤檢查的工具。Purify主要檢測:數組記憶體越界讀/寫,使用未初始化的記憶體,對已釋放的記憶體進行讀/寫,記憶體流失等。Insure++ 利12.
用其專利技術(源碼插裝和運行時指標跟蹤)能夠發現大量的記憶體操作錯誤,報告錯誤的原始碼行和執行軌跡。根據筆者的測試(基於98個有各種記憶體錯誤的 C++程式,涵蓋了典型情形),Insure++ 6.1都能準確檢測。
利用Windows結構化異常處理機制處理髮布版本軟體的記憶體崩潰
在程式的發布階段,應盡量減少程式錯誤尤其是記憶體崩潰。如果崩潰了,應該“優雅”地退出,盡量收集程式崩潰時的運行資訊以協助程式供應商後續的調試。要捕捉記憶體非法訪問並獲知非法訪問的指令地址、寄存器內容等資訊,需要用到 Windows的結構化異常處理(Structured Exception Handling,SEH)機制[6]。MiniDumpWriteDump是dbghelp.dll提供的一個 API函數(參考MSDN),用於轉儲使用者模式程式的一些資訊(比如堆棧情況等)並存為一個檔案(比如.dmp檔案),此檔案可以被微軟的調試器
(VC++或者WinDBG)利用進行事後調試。使用此函數需要dbghelp.h、dbghelp.lib和dbghelp.dll(這些檔案可以在 Windows Platform SDK中找到)。
要事後根據.dmp檔案調試代碼,需要為發布版本軟體產生debug symbols (pdb)檔案(開啟編譯器/DEBUG選項)。在拿到.dmp檔案以後,用VC++開啟.dmp檔案,然後調試執行(按F5鍵)。這樣,崩潰現場就會重現。文獻[5]基於上述的方法實現了崩潰報告系統