日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内存泄漏定位

發布時間:2025/5/22 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内存泄漏定位 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


今天調試程序,發現有內存泄漏但是沒有提示具體是哪一行,搞得我很頭疼。

第一種:通過"OutPut窗口"定位引發內存泄漏的代碼。

我們知道,MFC程序如果檢測到存在內存泄漏,退出程序的時候會在調試窗口提醒內存泄漏。例如:

class CMyApp : public CWinApp
{
public:
???BOOL InitApplication()
???{
???????int* leak = new int[10];
???????return TRUE;
???}
};

產生的內存泄漏報告大體如下:

Detected memory leaks!
Dumping objects ->
c:\work\test.cpp(186) : {52} normal block at 0x003C4410, 40 bytes long.
?Data: <????????????????> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

這挺好。問題是,如果我們不喜歡MFC,那么難道就沒有辦法?或者自己做?

呵呵,這不需要。其實,MFC也沒有自己做。內存泄漏檢測的工作是VC++的C運行庫做的。也就是說,只要你是VC++程序員,都可以很方便地檢測內存泄漏。我們還是給個樣例:

#include <crtdbg.h>

inline void EnableMemLeakCheck()
{
???_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
}

void main()
{
???EnableMemLeakCheck();
???int* leak = new int[10];
}

運行(提醒:不要按Ctrl+F5,按F5),你將發現,產生的內存泄漏報告與MFC類似,但有細節不同,如下:

Detected memory leaks!
Dumping objects ->
{52} normal block at 0x003C4410, 40 bytes long.
?Data: <????????????????> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

為什么呢?看下面。

定位內存泄漏由于哪一句話引起的

你已經發現程序存在內存泄漏。現在的問題是,我們要找泄漏的根源。

一般我們首先確定內存泄漏是由于哪一句引起。在MFC中,這一點很容易。你雙擊內存泄漏報告的文字,或者在Debug窗口中按F4,IDE就幫你定位到申請該內存塊的地方。對于上例,也就是這一句:

int* leak = new int[10];

這多多少少對你分析內存泄漏有點幫助。特別地,如果這個new僅對應一條delete(或者你把delete漏寫),這將很快可以確認問題的癥結。

我們前面已經看到,不使用MFC的時候,生成的內存泄漏報告與MFC不同,而且你立刻發現按F4不靈。那么難道MFC做了什么手腳?

其實不是,我們來模擬下MFC做的事情。看下例:

inline void EnableMemLeakCheck()
{
???_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
}

#ifdef _DEBUG
#define new???new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

void main()
{
???EnableMemLeakCheck();
???int* leak = new int[10];
}

再運行這個樣例,你驚喜地發現,現在內存泄漏報告和MFC沒有任何分別了。

第二種方法:直接定位指定內存塊錯誤的代碼行(下面轉)。

單確定了內存泄漏發生在哪一行,有時候并不足夠。特別是同一個new對應有多處釋放的情形。在實際的工程中,以下兩種情況很典型:

創建對象的地方是一個類工廠(ClassFactory)模式。很多甚至全部類實例由同一個new創建。對于此,定位到了new出對象的所在行基本沒有多大幫助。

COM對象。我們知道COM對象采用Reference Count維護生命周期。也就是說,對象new的地方只有一個,但是Release的地方很多,你要一個個排除。

那么,有什么好辦法,可以迅速定位內存泄漏?

答:有。

在內存泄漏情況復雜的時候,你可以用以下方法定位內存泄漏。這是我個人認為通用的內存泄漏追蹤方法中最有效的手段。

我們再回頭看看crtdbg生成的內存泄漏報告:

Detected memory leaks!
Dumping objects ->
c:\work\test.cpp(186) : {52} normal block at 0x003C4410, 40 bytes long.
?Data: <????????????????> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

除了產生該內存泄漏的內存分配語句所在的文件名、行號為,我們注意到有一個比較陌生的信息:{52}。這個整數值代表了什么意思呢?

其實,它代表了第幾次內存分配操作。象這個例子,{52}代表了第52次內存分配操作發生了泄漏。你可能要說,我只new過一次,怎么會是第52次?這很容易理解,其他的內存申請操作在C的初始化過程調用的唄。:)

有沒有可能,我們讓程序運行到第52次內存分配操作的時候,自動停下來,進入調試狀態?所幸,crtdbg確實提供了這樣的函數:即 long _CrtSetBreakAlloc(long nAllocID)。我們加上它:

inline void EnableMemLeakCheck()
{
???_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
}

#ifdef _DEBUG
#define new???new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

void main()
{
???EnableMemLeakCheck();
???_CrtSetBreakAlloc(52);
???int* leak = new int[10];
}

你發現,程序運行到 int* leak = new int[10]; 一句時,自動停下來進入調試狀態。細細體會一下,你可以發現,這種方式你獲得的信息遠比在程序退出時獲得文件名及行號有價值得多。因為報告泄漏文件名及行號,你獲得的只是靜態的信息,然而_CrtSetBreakAlloc則是把整個現場恢復,你可以通過對函數調用棧分析(我發現很多人不習慣看函數調用棧,如果你屬于這種情況,我強烈推薦你去補上這一課,因為它太重要了)以及其他在線調試技巧,來分析產生內存泄漏的原因。通常情況下,這種分析方法可以在5分鐘內找到肇事者。

當然,_CrtSetBreakAlloc要求你的程序執行過程是可還原的(多次執行過程的內存分配順序不會發生變化)。這個假設在多數情況下成立。不過,在多線程的情況下,這一點有時難以保證。

個人心得:我在用這種方法時開始沒看懂,后來在MSDN中也找到了這方面相關的信息,后來才會用。我感覺在這方面網上介紹的不夠詳細,下面我就相對詳細地解釋一下(為什么用“相對詳細”?本人比較懶)。首先說明一下,下面的函數不需要上面所添加的宏定義和"crtdbg.h"頭文件,也不需要EnableMemLeakCheck()函數。只需在main函數一開始運行 _CrtSetBreakAlloc(long (4459))函數。其中4459是申請內存的序號(上面有說明),然后F5運行(不需要設斷點),然后會出現“Find Source”這個對話框,點擊“取消”。然后會出現“User breakpoint called from code at xxxx”的對話框,點擊“確定”,會看到一些匯編的代碼(不要怕,其實我也看不懂,雖然原來學過點匯編),調出堆棧窗口(call stack),在其中的“main() line xxx + xxx bytes”上雙擊(或它的上一行雙擊,我的上一行是一個自定義函數,雙擊后直接定位到我new的地方,定位還是很準的,開始我懷疑,但最后檢查果然是這地方沒釋放)會定位到錯誤行。

第三種:用Ctrl+B來設定,不過現在好像忘了。效果根第二種方法基本一樣。

有人會問,既然第一種方法定位沒問題,為什么還要介紹第二種?其實在實際應用中,某些內存泄漏它沒有定位到哪一行的,只有內存塊的序號(有可能我用的不太會用),這個時候就需要用第二種方法。


【轉自】http://www.uml.org.cn/c++/201110272.asp

總結

以上是生活随笔為你收集整理的内存泄漏定位的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 毛片网站免费观看 | 在线看你懂得 | 视频一区 国产 | 少妇乱淫| 久久美女精品 | 国产伦理一区二区 | 久久精品一二三区 | 成人在线视频在线观看 | 亚洲字幕 | 日韩不卡毛片 | 久久久久久精 | 精品国产鲁一鲁一区二区三区 | av日韩中文字幕 | 先锋资源在线视频 | 国产熟女一区二区丰满 | 日韩www在线观看 | 黄色一级视频免费 | jizz俄罗斯| 国产一区二区在线视频 | 影音先锋在线视频 | 另类尿喷潮videofree | 红桃视频成人在线 | 五月花成人网 | 精品人妻一区二区免费视频 | 国产精品自拍99 | 亚洲无人区码一码二码三码的含义 | 伊人久久久久久久久久 | av噜噜| 日本黄色激情视频 | 欧美自拍在线 | 久久狠狠爱 | 熟妇大屁股一区二区三区视频 | 色综合社区| 潘金莲一级淫片aaaaa | 国产亚洲精品成人a | 福利社区一区二区 | 国产精品久久久久久亚洲av | 玖玖成人 | 已满18岁免费观看电视连续剧 | 午夜剧场福利社 | 自拍偷拍p | 久久最新视频 | 成人在线超碰 | 三级网站 | 日本xxxx18 | 久久精品国产亚洲av麻豆 | 香蕉久草 | 你懂的在线观看视频 | 青青网站| 毛片动漫 | 欧美国产成人精品一区二区三区 | 伊人伊色| 玖玖爱资源站 | 玖玖玖在线观看 | 韩国三级做爰高潮 | 日韩一区二区三区中文字幕 | 国产色无码精品视频国产 | 日韩免费久久 | 欧美爱爱小视频 | 波多野结衣办公室33分钟 | 成品短视频泡芙 | 狠狠干影院 | 男人插女人视频网站 | 亚洲欧美一区二区三区情侣bbw | 少妇做爰k8经典 | 日美韩av | 91精品国产一区二区三区蜜臀 | 天天干夜操| a级免费网站 | a√在线观看 | 91玉足脚交白嫩脚丫 | 日韩精品在线免费 | 久久久久久久久久久丰满 | 娇妻被老王脔到高潮失禁视频 | 免费大片黄在线观看视频网站 | 久久精品视频在线免费观看 | 欧美在线xxx | 播放毛片| 亚洲美女综合网 | 欧美日韩人妻精品一区在线 | 三日本三级少妇三级99 | 日韩淫片| 亚洲国产精品视频一区二区 | 浮生影视在线观看免费 | 操批网站| 天天看av | 日韩电影一二三区 | 中文字幕在线观看免费 | 五月婷婷六月综合 | 乱子伦一区二区三区 | 日韩av一区二区三区四区 | 黄色三级视频在线观看 | 日本不卡视频在线 | 国内成人精品 | jizz成熟丰满日本少妇 | 久久精彩| 在线天堂中文字幕 | 人妻少妇精品无码专区二区 | 国产三级午夜理伦三级 |