http://feikyo.cool.blog.163.com/blog/static/12206263820096223015272/
內(nèi)存泄漏定位 今天調(diào)試程序,發(fā)現(xiàn)有內(nèi)存泄漏但是沒有提示具體是哪一行,搞得我很頭疼。結(jié)果在網(wǎng)上搜索了一些資料,經(jīng)自己實踐后整理如下:
第一種:通過"OutPut窗口"定位引發(fā)內(nèi)存泄漏的代碼(下面轉(zhuǎn),我寫的沒原文好,也懶得寫)。 我們知道,MFC程序如果檢測到存在內(nèi)存泄漏,退出程序的時候會在調(diào)試窗口提醒內(nèi)存泄漏。例如:
class CMyApp : public CWinApp
Detected memory leaks! 呵呵,這不需要。其實,MFC也沒有自己做。內(nèi)存泄漏檢測的工作是VC++的C運行庫做的。也就是說,只要你是VC++程序員,都可以很方便地檢測內(nèi)存泄漏。我們還是給個樣例:
#include <crtdbg.h> inline void EnableMemLeakCheck() void main()
Detected memory leaks!
定位內(nèi)存泄漏由于哪一句話引起的你已經(jīng)發(fā)現(xiàn)程序存在內(nèi)存泄漏。現(xiàn)在的問題是,我們要找泄漏的根源。 一般我們首先確定內(nèi)存泄漏是由于哪一句引起。在MFC中,這一點很容易。你雙擊內(nèi)存泄漏報告的文字,或者在Debug窗口中按F4,IDE就幫你定位到申請該內(nèi)存塊的地方。對于上例,也就是這一句: int* leak = new int[10]; 這多多少少對你分析內(nèi)存泄漏有點幫助。特別地,如果這個new僅對應(yīng)一條delete(或者你把delete漏寫),這將很快可以確認(rèn)問題的癥結(jié)。 我們前面已經(jīng)看到,不使用MFC的時候,生成的內(nèi)存泄漏報告與MFC不同,而且你立刻發(fā)現(xiàn)按F4不靈。那么難道MFC做了什么手腳? 其實不是,我們來模擬下MFC做的事情??聪吕?/p>
inline void EnableMemLeakCheck() #ifdef _DEBUG void main()
第二種方法:直接定位指定內(nèi)存塊錯誤的代碼行(下面轉(zhuǎn))。 單確定了內(nèi)存泄漏發(fā)生在哪一行,有時候并不足夠。特別是同一個new對應(yīng)有多處釋放的情形。在實際的工程中,以下兩種情況很典型: 創(chuàng)建對象的地方是一個類工廠(ClassFactory)模式。很多甚至全部類實例由同一個new創(chuàng)建。對于此,定位到了new出對象的所在行基本沒有多大幫助。 答:有。 在內(nèi)存泄漏情況復(fù)雜的時候,你可以用以下方法定位內(nèi)存泄漏。這是我個人認(rèn)為通用的內(nèi)存泄漏追蹤方法中最有效的手段。 我們再回頭看看crtdbg生成的內(nèi)存泄漏報告: Detected memory leaks! 其實,它代表了第幾次內(nèi)存分配操作。象這個例子,{52}代表了第52次內(nèi)存分配操作發(fā)生了泄漏。你可能要說,我只new過一次,怎么會是第52次?這很容易理解,其他的內(nèi)存申請操作在C的初始化過程調(diào)用的唄。:) 有沒有可能,我們讓程序運行到第52次內(nèi)存分配操作的時候,自動停下來,進入調(diào)試狀態(tài)?所幸,crtdbg確實提供了這樣的函數(shù):即 long _CrtSetBreakAlloc(long nAllocID)。我們加上它: inline void EnableMemLeakCheck() #ifdef _DEBUG void main() 當(dāng)然,_CrtSetBreakAlloc要求你的程序執(zhí)行過程是可還原的(多次執(zhí)行過程的內(nèi)存分配順序不會發(fā)生變化)。這個假設(shè)在多數(shù)情況下成立。不過,在多線程的情況下,這一點有時難以保證。 個人心得:我在用這種方法時開始沒看懂,后來在MSDN中也找到了這方面相關(guān)的信息,后來才會用。我感覺在這方面網(wǎng)上介紹的不夠詳細(xì),下面我就相對詳細(xì)地解釋一下(為什么用“相對詳細(xì)”?本人比較懶)。首先說明一下,下面的函數(shù)不需要上面所添加的宏定義和"crtdbg.h"頭文件,也不需要EnableMemLeakCheck()函數(shù)。只需在main函數(shù)一開始運行 _CrtSetBreakAlloc(long (4459))函數(shù)。其中4459是申請內(nèi)存的序號(上面有說明),然后F5運行(不需要設(shè)斷點),然后會出現(xiàn)“Find Source”這個對話框,點擊“取消”。然后會出現(xiàn)“User breakpoint called from co (#) |
|
來自: 9loong > 《調(diào)試》