導航:首頁 > 解決方法 > 內存泄漏檢測方法

內存泄漏檢測方法

發布時間:2022-06-29 20:46:23

『壹』 怎麼排查這些內存泄漏

最原始的內存泄露測試
重復多次操作關鍵的可疑的路徑,從內存監控工具中觀察內存曲線,是否存在不斷上升的趨勢且不會在程序返回時明顯回落。
這種方式可以發現最基本,也是最明顯的內存泄露問題,對用戶價值最大,操作難度小,性價比極高。
MAT內存分析工具
2.1 MAT分析heap的總內存佔用大小來初步判斷是否存在泄露
在Devices 中,點擊要監控的程序。
點擊Devices視圖界面中最上方一排圖標中的「Update Heap」
點擊Heap視圖
點擊Heap視圖中的「Cause GC」按鈕
到此為止需檢測的進程就可以被監視。Heap視圖中部有一個Type叫做data object,即數據對象,也就是我們的程序中大量存在的類類型的對象。在data object一行中有一列是「Total Size」,其值就是當前進程中所有Java數據對象的內存總量,一般情況下,這個值的大小決定了是否會有內存泄漏。可以這樣判斷:
進入某應用,不斷的操作該應用,同時注意觀察data object的Total Size值,正常情況下Total Size值都會穩定在一個有限的范圍內,也就是說由於程序中的的代碼良好,沒有造成對象不被垃圾回收的情況。
所以說雖然我們不斷的操作會不斷的生成很多對象,而在虛擬機不斷的進行GC的過程中,這些對象都被回收了,內存佔用量會會落到一個穩定的水平;反之如果代碼中存在沒有釋放對象引用的情況,則data object的Total Size值在每次GC後不會有明顯的回落。隨著操作次數的增多Total Size的值會越來越大,直到到達一個上限後導致進程被殺掉。
2.2 MAT分析hprof來定位內存泄露的原因所在。
這是出現內存泄露後使用MAT進行問題定位的有效手段。
A)Dump出內存泄露當時的內存鏡像hprof,分析懷疑泄露的類:

B)分析持有此類對象引用的外部對象

C)分析這些持有引用的對象的GC路徑

D)逐個分析每個對象的GC路徑是否正常

從這個路徑可以看出是一個antiRadiationUtil工具類對象持有了MainActivity的引用導致MainActivity無法釋放。此時就要進入代碼分析此時antiRadiationUtil的引用持有是否合理(如果antiRadiationUtil持有了MainActivity的context導致節目退出後MainActivity無法銷毀,那一般都屬於內存泄露了)。
2.3 MAT對比操作前後的hprof來定位內存泄露的根因所在。
為查找內存泄漏,通常需要兩個 Dump結果作對比,打開 Navigator History面板,將兩個表的 Histogram結果都添加到 Compare Basket中去
A) 第一個HPROF 文件(usingFile > Open Heap Dump ).
B)打開Histogram view.
C)在NavigationHistory view里 (如果看不到就從Window >show view>MAT- Navigation History ), 右擊histogram然後選擇Add to Compare Basket .

D)打開第二個HPROF 文件然後重做步驟2和3.
E)切換到Compare Basket view, 然後點擊Compare the Results (視圖右上角的紅色」!」圖標)。

F)分析對比結果

可以看出兩個hprof的數據對象對比結果。
通過這種方式可以快速定位到操作前後所持有的對象增量,從而進一步定位出當前操作導致內存泄露的具體原因是泄露了什麼數據對象。
注意:
如果是用 MAT Eclipse 插件獲取的 Dump文件,不需要經過轉換則可在MAT中打開,Adt會自動進行轉換。
而手機SDk Dump 出的文件要經過轉換才能被 MAT識別,Android SDK提供了這個工具 hprof-conv (位於 sdk/tools下)
首先,要通過控制台進入到你的 android sdk tools 目錄下執行以下命令:
./hprof-conv xxx-a.hprof xxx-b.hprof
例如 hprof-conv input.hprof out.hprof
此時才能將out.hprof放在eclipse的MAT中打開。
手機管家內存泄露每日監控方案
目前手機管家的內存泄露每日監控會自動運行並輸出是否存在疑似泄露的報告郵件,不論泄露對象的大小。這其中涉及的核心技術主要是AspectJ,MLD自研工具(原理是虛引用)和UIAutomator。
3.1 AspectJ插樁監控代碼
手機管家目前使用一個ant腳本加入MLD的監控代碼,並通過AspectJ的語法實現插樁。
使用AspectJ的原因是可以靈活分離出項目源碼與監控代碼,通過不同的編譯腳本打包出不同用途的安裝測試包:如果測試包是經過Aspect插樁了MLD監控代碼的話,那麼運行完畢後會輸出指定格式的日誌文件,作為後續分析工作的數據基礎。
3.2 MLD實現監控核心邏輯
這是手機管家內的一個工具工程,正式打包不會打入,BVT等每日監控測試包可以打入。打入後可以通過諸如addObject介面(通過反射去檢查是否含有該工具並調用)來加入需要監控的檢測對象,這個工具會自動在指定時機(如退出管家)去檢測該對象是否發生泄漏。
這個內存泄露檢測的基本原理是:
虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用必須和引用隊列(ReferenceQueue)聯合使用(在虛引用函數就必須關聯指定)。當垃圾回收器准備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,自動把這個虛引用加入到與之關聯的引用隊列中。程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。
基於以上原理,MLD工具在調用介面addObject加入監控類型時,會為該類型對象增加一個虛引用,注意虛引用並不會影響該對象被正常回收。因此可以在ReferenceQueue引用隊列中統計未被回收的監控對象是否超過指定閥值。
利用PhantomReferences(虛引用)和ReferenceQueue(引用隊列),當PhantomReferences被加入到相關聯的ReferenceQueue時,則視該對象已經或處於垃圾回收器回收階段了。

MLD監控原理核心
目前手機管家已對大部分類完成內存泄露的監控,包括各種activity,service和view頁面等,務求在技術上能帶給用戶最順滑的產品體驗。
接下來簡單介紹下這個工具的判斷核心。根據虛引用監控到的內存狀態,需要通過多種策略來判斷是否存在內存泄露。
(1)最簡單的方式就是直接在加入監控時就為該類型設定最大存在個數,舉個例子,各個DAO對象理論上只能存在最多一個,因此一旦出現兩個相同的DAO,那一般都是泄露了;
(2)第二種情況是在頁面退出程序退出時,檢索gc後無法釋放的對象列表,這些對象類型也會成為內存泄露的懷疑對象;
(3)最後一種情況比較復雜,基本原理是根據歷史操作判斷對象數量的增長幅度。根據對象的增長通過最小二乘法擬合出該對象類型的增長速度,如果超過經驗值則會列入疑似泄露的對象列表。
3.3 UIAutomator完成重復操作的自動化
最後一步就很簡單了。這么多反復的UI操作,讓人工來點就太浪費人力了。我們使用UIAutomator來進行自動化操作測試。
目前手機管家的每日自動化測試已覆蓋各個功能的主路徑,並通過配置文件的方式來靈活驅動用例的增刪改查,最大限度保證了隨著版本推移用例的復用價值。
至此手機管家的內存泄露測試方案介紹完畢,也歡迎各路牛人交流溝通更多更強的內存泄露工具盒方案!
騰訊Bugly簡介
Bugly是騰訊內部產品質量監控平台的外發版本,其主要功能是App發布以後,對用戶側發生的Crash以及卡頓現象進行監控並上報,讓開發同學可以第一時間了解到App的質量情況,及時機型修改。目前騰訊內部所有的產品,均在使用其進行線上產品的崩潰監控。

『貳』 如何用VS工具檢測內存泄露

技術原理
檢測內存泄漏的主要工具是調試器和 CRT 調試堆函數。若要啟用調試堆函數,請在程序中包括以下語句:
#define CRTDBG_MAP_ALLOC
#include
#include
注意 #include 語句必須採用上文所示順序。如果更改了順序,所使用的函數可能無法正確工作。

通過包括 crtdbg.h,將 malloc 和 free 函數映射到其「Debug」版本_malloc_dbg 和_free_dbg,這些函數將跟蹤內存分配和釋放。此映射只在調試版本(在其中定義了 _DEBUG)中發生。發布版本使用普通的 malloc 和 free 函數。

#define 語句將 CRT 堆函數的基版本映射到對應的「Debug」版本。並非絕對需要該語句,但如果沒有該語句,內存泄漏轉儲包含的有用信息將較少。

在添加了上面所示語句之後,可以通過在程序中包括以下語句來轉儲內存泄漏信息:
_CrtDumpMemoryLeaks();
當在調試器下運行程序時,_CrtDumpMemoryLeaks 將在「輸出」窗口中顯示內存泄漏信息。內存泄漏信息如下所示:
Detected memory leaks!

Dumping objects ->

C:PROGRAM FILESVISUAL .cpp(20) : {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 mp complete.

如果不使用 #define _CRTDBG_MAP_ALLOC 語句,內存泄漏轉儲如下所示: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 mp complete.

未定義 _CRTDBG_MAP_ALLOC 時,所顯示的會是:

內存分配編號(在大括弧內)。
塊類型(普通、客戶端或 CRT)。
十六進制形式的內存位置。
以位元組為單位的塊大小。
前 16 位元組的內容(亦為十六進制)。
定義了 _CRTDBG_MAP_ALLOC 時,還會顯示在其中分配泄漏的內存的文件。文件名後括弧中的數字(本示例中為 20)是該文件內的行號。

轉到源文件中分配內存的行

在"輸出"窗口中雙擊包含文件名和行號的行。
-或-

在"輸出"窗口中選擇包含文件名和行號的行,然後按 F4 鍵。
_CrtSetDbgFlag

如果程序總在同一位置退出,則調用 _CrtDumpMemoryLeaks 足夠方便,但如果程序可以從多個位置退出該怎麼辦呢?不要在每個可能的出口放置一個對 _CrtDumpMemoryLeaks 的調用,可以在程序開始包括以下調用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

該語句在程序退出時自動調用 _CrtDumpMemoryLeaks。必須同時設置 _CRTDBG_ALLOC_MEM_DF 和 _CRTDBG_LEAK_CHECK_DF 兩個位域,如上所示。

說明
在VC++6.0的環境下,不再需要額外的添加
#define CRTDBG_MAP_ALLOC
#include
#include

只需要按F5,在調試狀態下運行,程序退出後在"輸出窗口"可以看到有無內存泄露。如果出現
Detected memory leaks!
Dumping objects ->

就有內存泄露。

確定內存泄露的地方
根據內存泄露的報告,有兩種消除的方法:

第一種比較簡單,就是已經把內存泄露映射到源文件的,可以直接在"輸出"窗口中雙擊包含文件名和行號的行。例如
Detected memory leaks!
Dumping objects ->
C:PROGRAM FILESVISUAL .cpp(20) : {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 mp complete.
C:PROGRAM FILESVISUAL .cpp(20)

就是源文件名稱和行號。

『叄』 如何測試軟體的內存泄露呢,是有什麼工具嗎

很高興為您解答。

怎樣檢測內存泄露 :

檢測內存泄漏的關鍵是要能截獲住對分配內存和釋放內存的函數的調用。截獲住這兩個函數,我們就能跟蹤每一塊內存的生命周期,比如,每當成功的分配一塊內存後,就把它的指針加入一個全局的list中;每當釋放一塊內存,再把它的指針從list中刪除。這樣,當程序結束的時候,list中剩餘的指針就是指向那些沒有被釋放的內存。這里只是簡單的描述了檢測內存泄漏的基本原理,詳細的演算法可以參見Steve Maguire的<<Writing Solid Code>>。

如果要檢測堆內存的泄漏,那麼需要截獲住malloc/realloc/free和new/delete就可以了(其實new/delete最終也是用malloc/free的,所以只要截獲前面一組即可)。對於其他的泄漏,可以採用類似的方法,截獲住相應的分配和釋放函數。比如,要檢測BSTR的泄漏,就需要截獲SysAllocString/SysFreeString;要檢測HMENU的泄漏,就需要截獲CreateMenu/ DestroyMenu。(有的資源的分配函數有多個,釋放函數只有一個,比如,SysAllocStringLen也可以用來分配BSTR,這時就需要截獲多個分配函數)

在Windows平台下,檢測內存泄漏的工具常用的一般有三種,MS C-Runtime Library內建的檢測功能;外掛式的檢測工具,諸如,Purify,BoundsChecker等;利用Windows NT自帶的Performance Monitor。這三種工具各有優缺點,MS C-Runtime Library雖然功能上較之外掛式的工具要弱,但是它是免費的;Performance Monitor雖然無法標示出發生問題的代碼,但是它能檢測出隱式的內存泄漏的存在,這是其他兩類工具無能為力的地方。

『肆』 如何在linux操作系統下檢測內存泄漏

內存泄漏是指程序動態申請的內存在使用完後沒有釋放,導致這段內存不能被操作系統回收再利用。
例如這段程序,申請了4個位元組的空間但沒有釋放,有4個位元組的內存泄漏。

#include <iostream>using namespace std;int main()
{ int *p = new int(1); cout <<*p<<endl; return 0}

隨著時間的推移,泄漏的內存越來越多,可用的內存越來越少,輕則性能受損,重則系統崩潰。

一般情況下,發生內存泄漏時,重啟就可以回收泄漏的內存。但是對於Linux,通常跑的是伺服器程序,不可以隨意重啟,在內存泄漏問題上就要格外小心。

內存泄漏特點
  1. 難復現 — 要運行到足夠長的時間才會暴露。

  2. 難定位 — 出錯位置是隨機的,看不出與內存泄漏的代碼有什麼聯系。

最簡單的方法

為了避免寫出內存泄漏的程序,通常會有這樣的編程規范,要求我們在寫程序時申請和釋放成對出現的。因為每一次申請都意味著必須有一次釋放與它相對應。

基於這個特點,一種簡單的方法就是在代碼中統計申請和釋放的次數,如果申請和釋放的數量不同,就認為是內存泄漏了。

#include "stdio.h"#include "stdlib.h"int malloc_count, free_count;void * my_malloc(int size)
{
malloc_count++; return malloc(size);
}void my_free(void *p)
{
free_count++; free(p);
}int main()
{
count = 0; int *p1 = (int *)my_malloc(sizeif(int)) int *p2 = (int *)my_malloc(sizeif(int)) printf("%d, %d", p1, p2);
my_free(p1); if(malloc_count != free_count) printf("memory leak! "); return 0}方法分析

直觀,容易理解,容易實現

1.該方法要求運行結束時對運行中產生的列印分析才能知道結果。

2.該方法要求封裝所有申請和釋放空間的函數,並在調用的地方修改成調用封裝後的函數。雖然C中申請/釋放內存介面並不多,但是對於一個大型的項目,調用這些介面的地方卻是很多的,要全部替換是一個比較大的工作量。

3.只對C語言適用,不能應用於C++

4.對於所調用的庫不適用。如果希望應用於庫,則要修改庫代碼

5.只能檢測是否泄漏,卻沒有具體信息,比如泄漏了多少空間

6.不能說明是哪一行代碼引起了泄漏

改進

這種方法雖然簡單的,卻有許多的不足,無法真正應用於項目中。欲知怎樣改進,且看下回分解。

『伍』 如何在linux下檢測內存泄漏

檢測內存泄露主要有以下5種方法:1、在需要內存泄漏檢查的代碼的開始調用void mtrace(void) (該函數在頭文件mcheck.h中有聲明)。mtrace為malloc等函數安裝hook,用於記錄內存分配信息.在需要內存泄漏檢查的代碼的結束調用void muntrace(void)。注意: 一般情況下不要調用muntrace, 而讓程序自然結束. 因為可能有些釋放內存代碼要到muntrace之後才運行. 2、用debug模式編譯被檢查代碼(-g或-ggdb)。3、設置環境變數MALLOC_TRACE為一文件名, 這一文件將存有內存分配信息。 4、運行被檢查程序, 直至結束或muntrace被調用。5、用mtrace命令解析內存分配Log文件($MALLOC_TRACE) (mtrace foo $MALLOC_TRACE, where foo is the executible name) 如果有內存泄漏,mtrace會輸出分配泄漏 內存的代碼位置,以及分配數量。

『陸』 如何檢查內存泄露問題

簡單說明了一下沒有工具的情況如何運用VC庫中的工具來檢查代碼的內存泄漏問題。
一: 內存泄漏
內存泄漏是編程中常常見到的一個問題,內存泄漏往往會一種奇怪的方式來表現出來,基本上每個程序都表現出不同的方式。 但是一般最後的結果只有兩個,一個是程序當掉,一個是系統內存不足。 還有一種就是比較介於中間的結果程序不會當,但是系統的反映時間明顯降低,需要定時的Reboot才會正常。
有 一個很簡單的辦法來檢查一個程序是否有內存泄漏。就是是用Windows的任務管理器(Task Manager)。運行程序,然後在任務管理器裡面查看 「內存使用」和」虛擬內存大小」兩項,當程序請求了它所需要的內存之後,如果虛擬內存還是持續的增長的話,就說明了這個程序有內存泄漏問題。 當然如果內存泄漏的數目非常的小,用這種方法可能要過很長時間才能看的出來。
當然最簡單的辦法大概就是用CompuWare的BoundChecker 之類的工具來檢測了,不過這些工具的價格對於個人來講稍微有點奢侈了。
如果是已經發布的程序,檢查是否有內存泄漏是又費時又費力。所以內存泄漏應該在Code的生成過程就要時刻進行檢查。
二: 原因
內存泄漏產生的原因一般是三種情況:
分配完內存之後忘了回收;
程序Code有問題,造成沒有辦法回收;
某些API函數操作不正確,造成內存泄漏。
1. 內存忘記回收,這個是不應該的事情。但是也是在代碼種很常見的問題。分配內存之後,用完之後,就一定要回收。如果不回收,那就造成了內存的泄漏,造成內存泄漏的Code如果被經常調用的話,那內存泄漏的數目就會越來越多的。從而影響整個系統的運行。比如下面的代碼:
for (int =0;I<100;I++)
{
Temp = new BYTE[100];
}
就會產生 100*100Byte的內存泄漏。
2. 在某些時候,因為代碼上寫的有問題,會導致某些內存想回收都收不回來,比如下面的代碼:
Temp1 = new BYTE[100];
Temp2 = new BYTE[100];
Temp2 = Temp1;
這樣,Temp2的內存地址就丟掉了,而且永遠都找不回了,這個時候Temp2的內存空間想回收都沒有辦法。
3. API函 數應用不當,在Windows提供API函數裡面有一些特殊的API,比如FormatMessage。 如果你給它參數中有FORMAT_MESSAGE_ALLOCATE_BUFFER,它會在函數內部New一塊內存Buffer出來。但是這個 buffer需要你調用LocalFree來釋放。 如果你忘了,那就會產生內存泄漏。
三: 檢查方法
一 般的內存泄漏檢查的確是很困難,但是也不是完全沒有辦法。如果你用VC的庫來寫東西的話,那麼很幸運的是,你已經有了很多檢查內存泄漏的工具,只是你想不 想用的問題了。Visual C++的Debug版本的C運行庫(C Runtime Library)。它已經提供好些函數來幫助你診斷你的代碼和跟蹤內存泄漏。 而且最方便的地方是這些函數在Release版本中完全不起任何作用,這樣就不會影響你的Release版本程序的運行效率。
比如下面的例子裡面,有一個明細的內存泄漏。當然如果只有這么幾行代碼的話,是很容易看出有內存泄漏的。但是想在成千上萬行代碼裡面檢查內存泄漏問題就不是那麼容易了。
char * pstr = new char[5];
lstrcpy(pstr,"Memory leak");
如 果我們在Debug版本的Code裡面對堆(Heap)進行了操作,包括malloc, free, calloc, realloc, new 和 delete可以利用VC Debug運行時庫中堆Debug函數來做堆的完整性和安全性檢查。比如上面的代碼,lstrcpy的操作明顯破壞了pstr的堆結構。使其溢出,並破壞 了臨近的數據。那我們可以在調用lstrcpy之後的代碼裡面加入 _CrtCheckMemory函數。_CrtCheckMemory函數發現前面的lstrcpy使得pstr的堆結構被破壞,會輸出這樣的報告:
emory check error at 0x00372FA5 = 0x79, should be 0xFD.
memory check error at 0x00372FA6 = 0x20, should be 0xFD.
memory check error at 0x00372FA7 = 0x6C, should be 0xFD.
memory check error at 0x00372FA8 = 0x65, should be 0xFD.
DAMAGE: after Normal block (#41) at 0x00372FA0.
Normal located at 0x00372FA0 is 5 bytes long.
它 告訴說 pstr的長度應該時5個Bytes,但是在5Bytes後面的幾個Bytes也被非法改寫了。提醒你產生了越界操作。_CrtCheckMemory 的返回值只有TRUE和FALSE,那麼你可以用_ASSERTE()來報告出錯信息。 上面的語句可以換成 _ASSERTE(_CrtCheckMemory()); 這樣Debug版本的程序在運行的時候就會彈出一個警告對話框,這樣就不用在運行時候一直盯著Output窗口看了。這個時候按Retry,就可以進入源 代碼調試了。看看問題到底出在哪裡
其他類似的函數還有 _CrtDbgReport, _CrtDoForAllClientObjects, _CrtDumpMemoryLeaks,_CrtIsValidHeapPointer, _CrtIsMemoryBlock, _CrtIsValidPointer,_CrtMemCheckpoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince, _CrtMemDumpStatistics, _CrtSetAllocHook, _CrtSetBreakAlloc, _CrtSetDbgFlag,_CrtSetDumpClient, _CrtSetReportFile, _CrtSetReportHook, _CrtSetReportMode
這 些函數全部都可以用來在Debug版本中檢查內存的使用情況。具體怎麼使用這些函數就不在這里說明了,各位可以去查查MSDN。在這些函數中用處比較大 的,或者說使用率會比較高的函數是_CrtMemCheckpoint, 設置一個內存檢查點。這個函數會取得當前內存的運行狀態。 _CrtMemDifference 檢查兩種內存狀態的異同。 _CrtMemDumpAllObjectsSince 從程序運行開始,或者從某個內存檢查點開始Dump出堆中對象的信息。還有就是_CrtDumpMemoryLeaks當發生內存溢出的時候Dump出堆 中的內存信息。 _CrtDumpMemoryLeaks一般都在有懷疑是內存泄漏的代碼後面調用。比如下面的例子:
#include <windows.h>
#include <crtdbg.h>
void main()
{
char * pstr;
pstr = new char[5];
_CrtDumpMemoryLeaks();
}
輸出:
Detected memory leaks! à提醒你,代碼有內存泄漏.
Dumping objects ->
{44} normal block at 0x00372DB8, 5 bytes long.
Data: < > CD CD CD CD CD
Object mp complete.
如 果你雙擊包含行文件名的輸出行,指針將會跳到源文件中內存被分配地方的行。當無法確定那些代碼產生了內存泄漏的時候,我們就需要進行內存狀態比較。在可疑 的代碼段的前後設置內存檢查點,比較內存使用是否有可疑的變化。以確定內存是否有泄漏。為此要先定義三個_CrtMemState 對象來保存要比較的內存狀態。兩個是用來比較,一個用了保存前面兩個之間的區別。
_CrtMemState Sh1,Sh2,Sh_Diff;
char *pstr1 = new char[100];
_CrtMemCheckPoint(&Sh1); ->設置第一個內存檢查點
char *pstr2 = new char[100];
_CrtMemCheckPoint(&Sh2); ->設置第二個內存檢查點
_CrtMemDifference(&Sh_Diff, &Sh1, &Sh2); ->檢查變化
_CrtMemDumpAllObjectsSince(&Sh_Diff); ->Dump變化
如 果你的程序中使用了MFC類庫,那麼內存泄漏的檢查方法就相當的簡單了。因為Debug版本的MFC本身就提供一部分的內存泄漏檢查。 大部分的new 和delete沒有配對使用而產生的內存泄漏,MFC都會產生報告。這個主要是因為MFC重載了Debug版本的new 和delete操作符, 並且對前面提到的API函數重新進行了包裝。在MFC類庫中檢查內存泄漏的Class就叫 CMemoryState,它重新包裝了了_CrtMemState,_CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince這些函數。並對於其他的函數提供了Afx開頭的函數,供MFC程序使用。比如 AfxCheckMemory, AfxDumpMemoryLeaks 這些函數的基本用法同上面提到的差不多。 CMemoryState和相關的函數的定義都在Afx.h這個頭文件中。 有個簡單的辦法可以跟蹤到這些函數的聲明。在VC中找到MFC程序代碼中下面的代碼, 一般都在X.cpp的開頭部分
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
把 游標移到DEBUG_NEW上面 按F12,就可以進入Afx.h中定義這些Class和函數的代碼部分。 VC中內存泄漏的常規檢查辦法主要是上面的兩種。當然這兩種方法只是針對於Debug版本的Heap的檢查。如果Release版本中還有內存泄漏,那麼 檢查起來就麻煩很多了。
4 .總結:
實際上Heap的內存泄漏問題是相當的好查的。VC的提供的檢查工具也不太少,但是如果是棧出了什麼問題,恐怕就麻煩很多了。棧出問題,一般不會產生內存泄漏,但是你的代碼的邏輯上很有可能會有影響。這個是最最痛苦的事情。 編程,就是小心,小心再小心而已。

『柒』 如何檢測內存泄漏

內存泄漏指由於疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內存泄漏並非指內存在物理上的消失,而是應用程序分配某段內存後,由於設計錯誤,失去了對該段內存的控制,因而造成了內存的浪費。
可以使用相應的軟體測試工具對軟體進行檢測。
1. ccmalloc——Linux和Solaris下對C和C++程序的簡單的使用內存泄漏和malloc調試庫。
2. Dmalloc——Debug Malloc Library.
3. Electric
Fence——Linux分發版中由Bruce Perens編寫的malloc()調試庫。
4. Leaky——Linux下檢測內存泄漏的程序。
5. LeakTracer——Linux、Solaris和HP-UX下跟蹤和分析C++程序中的內存泄漏。
6. MEMWATCH——由Johan
Lindh編寫,是一個開放源代碼C語言內存錯誤檢測工具,主要是通過gcc的precessor來進行。
7. Valgrind——Debugging and profiling Linux programs, aiming at
programs written in C and C++.
8. KCachegrind——A visualization tool for the profiling data
generated by Cachegrind and Calltree.
9. Leak
Monitor——一個Firefox擴展,能找出跟Firefox相關的泄漏類型。
10. IE Leak Detector
(Drip/IE Sieve)——Drip和IE Sieve leak
detectors幫助網頁開發員提升動態網頁性能通過報告可避免的因為IE局限的內存泄漏。
11. Windows Leaks
Detector——探測任何Win32應用程序中的任何資源泄漏(內存,句柄等),基於Win API調用鉤子。
12. SAP Memory
Analyzer——是一款開源的JAVA內存分析軟體,可用於輔助查找JAVA程序的內存泄漏,能容易找到大塊內存並驗證誰在一直佔用它,它是基於Eclipse
RCP(Rich Client Platform),可以下載RCP的獨立版本或者Eclipse的插件。
13. DTrace——即動態跟蹤Dynamic
Tracing,是一款開源軟體,能在Unix類似平台運行,用戶能夠動態檢測操作系統內核和用戶進程,以更精確地掌握系統的資源使用狀況,提高系統性能,減少支持成本,並進行有效的調節。
14. IBM Rational PurifyPlus——幫助開發人員查明C/C++、託管。NET、Java和VB6代碼中的性能和可靠性錯誤。PurifyPlus
將內存錯誤和泄漏檢測、應用程序性能描述、代碼覆蓋分析等功能組合在一個單一、完整的工具包中。
15. Parasoft Insure++——針對C/C++應用的運行時錯誤自動檢測工具,它能夠自動監測C/C++程序,發現其中存在著的內存破壞、內存泄漏、指針錯誤和I/O等錯誤。並通過使用一系列獨特的技術(SCI技術和變異測試等),徹底的檢查和測試我們的代碼,精確定位錯誤的准確位置並給出詳細的診斷信息。能作為Microsoft
Visual C++的一個插件運行。
16. Compuware DevPartner for Visual C++ BoundsChecker
Suite——為C++開發者設計的運行錯誤檢測和調試工具軟體。作為Microsoft Visual Studio和C++ 6.0的一個插件運行。
17. Electric Software GlowCode——包括內存泄漏檢查,code
profiler,函數調用跟蹤等功能。給C++和。Net開發者提供完整的錯誤診斷,和運行時性能分析工具包。
18. Compuware DevPartner Java
Edition——包含Java內存檢測,代碼覆蓋率測試,代碼性能測試,線程死鎖,分布式應用等幾大功能模塊。
19. Quest JProbe——分析Java的內存泄漏。
20. ej-technologies JProfiler——一個全功能的Java剖析工具,專用於分析J2SE和J2EE應用程序。它把CPU、執行緒和內存的剖析組合在一個強大的應用中。JProfiler可提供許多IDE整合和應用伺服器整合用途。JProfiler直覺式的GUI讓你可以找到效能瓶頸、抓出內存泄漏、並解決執行緒的問題。4.3.2注冊碼:A-G666#76114F-1olm9mv1i5uuly#0126
21. BEA JRockit——用來診斷Java內存泄漏並指出根本原因,專門針對Intel平台並得到優化,能在Intel硬體上獲得最高的性能。
22. SciTech Software AB .NET Memory
Profiler——找到內存泄漏並優化內存使用針對C#,VB.Net,或其它。Net程序。
23. YourKit .NET & Java Profiler——業界領先的Java和。NET程序性能分析工具。
24. AutomatedQA AQTime——AutomatedQA的獲獎產品performance profiling和memory
debugging工具集的下一代替換產品,支持Microsoft, Borland, Intel, Compaq 和
GNU編譯器。可以為。NET和Windows程序生成全面細致的報告,從而幫助您輕松隔離並排除代碼中含有的性能問題和內存/資源泄露問題。支持。Net
1.0,1.1,2.0,3.0和Windows 32/64位應用程序。
25. JavaScript Memory Leak Detector——微軟全球產品開發歐洲團隊(Global Proct
Development- Europe team, GPDE)
發布的一款調試工具,用來探測JavaScript代碼中的內存泄漏,運行為IE系列的一個插件。

『捌』 如何用monitor看內存泄漏

簡單說明了一下沒有工具的情況如何運用VC庫中的工具來檢查代碼的內存泄漏問題。
一: 內存泄漏
內存泄漏是編程中常常見到的一個問題,內存泄漏往往會一種奇怪的方式來表現出來,基本上每個程序都表現出不同的方式。 但是一般最後的結果只有兩個,一個是程序當掉,一個是系統內存不足。 還有一種就是比較介於中間的結果程序不會當,但是系統的反映時間明顯降低,需要定時的Reboot才會正常。
有 一個很簡單的辦法來檢查一個程序是否有內存泄漏。就是是用Windows的任務管理器(Task Manager)。運行程序,然後在任務管理器裡面查看 逗內存使用地和地虛擬內存大小地兩項,當程序請求了它所需要的內存之後,如果虛擬內存還是持續的增長的話,就說明了這個程序有內存泄漏問題。 當然如果內存泄漏的數目非常的小,用這種方法可能要過很長時間才能看的出來。
當然最簡單的辦法大概就是用CompuWare的BoundChecker 之類的工具來檢測了,不過這些工具的價格對於個人來講稍微有點奢侈了。
如果是已經發布的程序,檢查是否有內存泄漏是又費時又費力。所以內存泄漏應該在Code的生成過程就要時刻進行檢查。
二: 原因
內存泄漏產生的原因一般是三種情況:
分配完內存之後忘了回收;
程序Code有問題,造成沒有辦法回收;
某些API函數操作不正確,造成內存泄漏。
1. 內存忘記回收,這個是不應該的事情。但是也是在代碼種很常見的問題。分配內存之後,用完之後,就一定要回收。如果不回收,那就造成了內存的泄漏,造成內存泄漏的Code如果被經常調用的話,那內存泄漏的數目就會越來越多的。從而影響整個系統的運行。比如下面的代碼:
for (int =0;I<100;I++)
{
Temp = new BYTE[100];
}
就會產生 100*100Byte的內存泄漏。
2. 在某些時候,因為代碼上寫的有問題,會導致某些內存想回收都收不回來,比如下面的代碼:
Temp1 = new BYTE[100];
Temp2 = new BYTE[100];
Temp2 = Temp1;
這樣,Temp2的內存地址就丟掉了,而且永遠都找不回了,這個時候Temp2的內存空間想回收都沒有辦法。
3. API函 數應用不當,在Windows提供API函數裡面有一些特殊的API,比如FormatMessage。 如果你給它參數中有FORMAT_MESSAGE_ALLOCATE_BUFFER,它會在函數內部New一塊內存Buffer出來。但是這個 buffer需要你調用LocalFree來釋放。 如果你忘了,那就會產生內存泄漏。
三: 檢查方法
一 般的內存泄漏檢查的確是很困難,但是也不是完全沒有辦法。如果你用VC的庫來寫東西的話,那麼很幸運的是,你已經有了很多檢查內存泄漏的工具,只是你想不 想用的問題了。Visual C++的Debug版本的C運行庫(C Runtime Library)。它已經提供好些函數來幫助你診斷你的代碼和跟蹤內存泄漏。 而且最方便的地方是這些函數在Release版本中完全不起任何作用,這樣就不會影響你的Release版本程序的運行效率。
比如下面的例子裡面,有一個明細的內存泄漏。當然如果只有這么幾行代碼的話,是很容易看出有內存泄漏的。但是想在成千上萬行代碼裡面檢查內存泄漏問題就不是那麼容易了。
char * pstr = new char[5];
lstrcpy(pstr,"Memory leak");
如 果我們在Debug版本的Code裡面對堆(Heap)進行了操作,包括malloc, free, calloc, realloc, new 和 delete可以利用VC Debug運行時庫中堆Debug函數來做堆的完整性和安全性檢查。比如上面的代碼,lstrcpy的操作明顯破壞了pstr的堆結構。使其溢出,並破壞 了臨近的數據。那我們可以在調用lstrcpy之後的代碼裡面加入 _CrtCheckMemory函數。_CrtCheckMemory函數發現前面的lstrcpy使得pstr的堆結構被破壞,會輸出這樣的報告:
emory check error at 0x00372FA5 = 0x79, should be 0xFD.
memory check error at 0x00372FA6 = 0x20, should be 0xFD.
memory check error at 0x00372FA7 = 0x6C, should be 0xFD.
memory check error at 0x00372FA8 = 0x65, should be 0xFD.
DAMAGE: after Normal block (#41) at 0x00372FA0.
Normal located at 0x00372FA0 is 5 bytes long.
它 告訴說 pstr的長度應該時5個Bytes,但是在5Bytes後面的幾個Bytes也被非法改寫了。提醒你產生了越界操作。_CrtCheckMemory 的返回值只有TRUE和FALSE,那麼你可以用_ASSERTE()來報告出錯信息。 上面的語句可以換成 _ASSERTE(_CrtCheckMemory()); 這樣Debug版本的程序在運行的時候就會彈出一個警告對話框,這樣就不用在運行時候一直盯著Output窗口看了。這個時候按Retry,就可以進入源 代碼調試了。看看問題到底出在哪裡。
其他類似的函數還有 _CrtDbgReport, _CrtDoForAllClientObjects, _CrtDumpMemoryLeaks,_CrtIsValidHeapPointer, _CrtIsMemoryBlock, _CrtIsValidPointer,_CrtMemCheckpoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince, _CrtMemDumpStatistics, _CrtSetAllocHook, _CrtSetBreakAlloc, _CrtSetDbgFlag,_CrtSetDumpClient, _CrtSetReportFile, _CrtSetReportHook, _CrtSetReportMode
這 些函數全部都可以用來在Debug版本中檢查內存的使用情況。具體怎麼使用這些函數就不在這里說明了,各位可以去查查MSDN。在這些函數中用處比較大 的,或者說使用率會比較高的函數是_CrtMemCheckpoint, 設置一個內存檢查點。這個函數會取得當前內存的運行狀態。 _CrtMemDifference 檢查兩種內存狀態的異同。 _CrtMemDumpAllObjectsSince 從程序運行開始,或者從某個內存檢查點開始Dump出堆中對象的信息。還有就是_CrtDumpMemoryLeaks當發生內存溢出的時候Dump出堆 中的內存信息。 _CrtDumpMemoryLeaks一般都在有懷疑是內存泄漏的代碼後面調用。比如下面的例子:
#include <windows.h>
#include <crtdbg.h>
void main()
{
char * pstr;
pstr = new char[5];
_CrtDumpMemoryLeaks();
}
輸出:
Detected memory leaks! à提醒你,代碼有內存泄漏.
Dumping objects ->
{44} normal block at 0x00372DB8, 5 bytes long.
Data: < > CD CD CD CD CD
Object mp complete.
如 果你雙擊包含行文件名的輸出行,指針將會跳到源文件中內存被分配地方的行。當無法確定那些代碼產生了內存泄漏的時候,我們就需要進行內存狀態比較。在可疑 的代碼段的前後設置內存檢查點,比較內存使用是否有可疑的變化。以確定內存是否有泄漏。為此要先定義三個_CrtMemState 對象來保存要比較的內存狀態。兩個是用來比較,一個用了保存前面兩個之間的區別。
_CrtMemState Sh1,Sh2,Sh_Diff;
char *pstr1 = new char[100];
_CrtMemCheckPoint(&Sh1); ->設置第一個內存檢查點
char *pstr2 = new char[100];
_CrtMemCheckPoint(&Sh2); ->設置第二個內存檢查點
_CrtMemDifference(&Sh_Diff, &Sh1, &Sh2); ->檢查變化
_CrtMemDumpAllObjectsSince(&Sh_Diff); ->Dump變化
如 果你的程序中使用了MFC類庫,那麼內存泄漏的檢查方法就相當的簡單了。因為Debug版本的MFC本身就提供一部分的內存泄漏檢查。 大部分的new 和delete沒有配對使用而產生的內存泄漏,MFC都會產生報告。這個主要是因為MFC重載了Debug版本的new 和delete操作符, 並且對前面提到的API函數重新進行了包裝。在MFC類庫中檢查內存泄漏的Class就叫 CMemoryState,它重新包裝了了_CrtMemState,_CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince這些函數。並對於其他的函數提供了Afx開頭的函數,供MFC程序使用。比如 AfxCheckMemory, AfxDumpMemoryLeaks 這些函數的基本用法同上面提到的差不多。 CMemoryState和相關的函數的定義都在Afx.h這個頭文件中。 有個簡單的辦法可以跟蹤到這些函數的聲明。在VC中找到MFC程序代碼中下面的代碼, 一般都在X.cpp的開頭部分
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
把 游標移到DEBUG_NEW上面 按F12,就可以進入Afx.h中定義這些Class和函數的代碼部分。 VC中內存泄漏的常規檢查辦法主要是上面的兩種。當然這兩種方法只是針對於Debug版本的Heap的檢查。如果Release版本中還有內存泄漏,那麼 檢查起來就麻煩很多了。
4 .總結:
實際上Heap的內存泄漏問題是相當的好查的。VC的提供的檢查工具也不太少,但是如果是棧出了什麼問題,恐怕就麻煩很多了。棧出問題,一般不會產生內存泄漏,但是你的代碼的邏輯上很有可能會有影響。這個是最最痛苦的事情。 編程,就是小心,小心再小心而已。

『玖』 VC6.0如何啟用內存泄漏檢測機制

VC++ IDE 的默認狀態是沒有啟用內存泄漏檢測機制的,也就是說即使某段代碼有內存泄漏,調試會話的 Output 窗口的 Debug 頁不會輸出有關內存泄漏信息。你必須設定兩個最基本的機關來啟用內存泄漏檢測機制。
一是使用調試堆函數:
#define _CRTDBG_MAP_ALLOC
#include<stdlib.h>
#include<crtdbg.h>
注意:#include 語句的順序。如果更改此順序,所使用的函數可能無法正確工作。
通過包含 crtdbg.h 頭文件,可以將 malloc 和 free 函數映射到其「調試」版本 _malloc_dbg 和 _free_dbg,這些函數會跟蹤內存分配和釋放。此映射只在調試(Debug)版本(也就是要定義 _DEBUG)中有效。發行版本(Release)使用普通的 malloc 和 free 函數。
#define 語句將 CRT 堆函數的基礎版本映射到對應的「調試」版本。該語句不是必須的,但如果沒有該語句,那麼有關內存泄漏的信息會不全。
二是在需要檢測內存泄漏的地方添加下面這條語句來輸出內存泄漏信息:
_CrtDumpMemoryLeaks();
當在調試器下運行程序時,_CrtDumpMemoryLeaks 將在 Output 窗口的 Debug 頁中顯示內存泄漏信息。比如:
Detected memory leaks!
Dumping objects ->
C:\Temp\memleak\memleak.cpp(15) : {45} normal block at 0x00441BA0, 2 bytes long.
Data: <AB> 41 42
c:\program files\microsoft visual studio\vc98\include\crtdbg.h(552) : {44} normal block at 0x00441BD0, 33 bytes long.
Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD
c:\program files\microsoft visual studio\vc98\include\crtdbg.h(552) : {43} normal block at 0x00441C20, 40 bytes long.
Data: < C > 08 02 43 00 16 00 00 00 00 00 00 00 00 00 00 00
Object mp complete.
如果不使用 #define _CRTDBG_MAP_ALLOC 語句,內存泄漏的輸出是這樣的:
Detected memory leaks!
Dumping objects ->
{45} normal block at 0x00441BA0, 2 bytes long.
Data: <AB> 41 42
{44} normal block at 0x00441BD0, 33 bytes long.
Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD
{43} normal block at 0x00441C20, 40 bytes long.
Data: < C > C0 01 43 00 16 00 00 00 00 00 00 00 00 00 00 00
Object mp complete.
根據這段輸出信息,你無法知道在哪個源程序文件里發生了內存泄漏。下面我們來研究一下輸出信息的格式。第一行和第二行沒有什麼可說的,從第三行開始:
xx}:花括弧內的數字是內存分配序號,本文例子中是 {45},{44},{43};
block:內存塊的類型,常用的有三種:normal(普通)、client(客戶端)或 CRT(運行時);本文例子中是:normal block;
用十六進制格式表示的內存位置,如:at 0x00441BA0 等;
以位元組為單位表示的內存塊的大小,如:32 bytes long;
前16位元組的內容(也是用十六進制格式表示),如:Data: <AB> 41 42 等;
仔細觀察不難發現,如果定義了 _CRTDBG_MAP_ALLOC ,那麼在內存分配序號前面還會顯示在其中分配泄漏內存的文件名,以及文件名後括弧中的數字表示發生泄漏的代碼行號,比如:
C:\Temp\memleak\memleak.cpp(15)
雙擊 Output 窗口中此文件名所在的輸出行,便可跳到源程序文件分配該內存的代碼行(也可以選中該行,然後按 F4,效果一樣) ,這樣一來我們就很容易定位內存泄漏是在哪裡發生的了,因此,_CRTDBG_MAP_ALLOC 的作用顯而易見。
使用 _CrtSetDbgFlag
如果程序只有一個出口,那麼調用 _CrtDumpMemoryLeaks 的位置是很容易選擇的。但是,如果程序可能會在多個地方退出該怎麼辦呢?在每一個可能的出口處調用 _CrtDumpMemoryLeaks 肯定是不可取的,那麼這時可以在程序開始處包含下面的調用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
這條語句無論程序在什麼地方退出都會自動調用 _CrtDumpMemoryLeaks。注意:這里必須同時設置兩個位域標志:_CRTDBG_ALLOC_MEM_DF 和 _CRTDBG_LEAK_CHECK_DF。
設置 CRT 報告模式
默認情況下,_CrtDumpMemoryLeaks 將內存泄漏信息 mp 到 Output 窗口的 Debug 頁, 如果你想將這個輸出定向到別的地方,可以使用 _CrtSetReportMode 進行重置。如果你使用某個庫,它可能將輸出定向到另一位置。此時,只要使用以下語句將輸出位置設回 Output 窗口即可:
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
有關使用 _CrtSetReportMode 的詳細信息,請參考 MSDN 庫關於 _CrtSetReportMode 的描述。
解釋內存塊類型
前面已經說過,內存泄漏報告中把每一塊泄漏的內存分為 normal(普通塊)、client(客戶端塊)和 CRT 塊。事實上,需要留心和注意的也就是 normal 和 client,即普通塊和客戶端塊。
normal block(普通塊):這是由你的程序分配的內存。
client block(客戶塊):這是一種特殊類型的內存塊,專門用於 MFC 程序中需要析構函數的對象。MFC new 操作符視具體情況既可以為所創建的對象建立普通塊,也可以為之建立客戶塊。
CRT block(CRT 塊):是由 C RunTime Library 供自己使用而分配的內存塊。由 CRT 庫自己來管理這些內存的分配與釋放,我們一般不會在內存泄漏報告中發現 CRT 內存泄漏,除非程序發生了嚴重的錯誤(例如 CRT 庫崩潰)。
除了上述的類型外,還有下面這兩種類型的內存塊,它們不會出現在內存泄漏報告中。
free block(空閑塊):已經被釋放(free)的內存塊。
Ignore block(忽略塊):這是程序員顯式聲明過不要在內存泄漏報告中出現的內存塊。
如何在內存分配序號處設置斷點?
在內存泄漏報告中,的文件名和行號可告訴分配泄漏的內存的代碼位置,但僅僅依賴這些信息來了解完整的泄漏原因是不夠的。因為一個程序在運行時,一段分配內存的代碼可能會被調用很多次,只要有一次調用後沒有釋放內存就會導致內存泄漏。為了確定是哪些內存沒有被釋放,不僅要知道泄漏的內存是在哪裡分配的,還要知道泄漏產生的條件。這時內存分配序號就顯得特別有用——這個序號就是文件名和行號之後的花括弧里的那個數字。
例如,在本文例子代碼的輸出信息中,「45」是內存分配序號,意思是泄漏的內存是你程序中分配的第四十五個內存塊:
Detected memory leaks!
Dumping objects ->
C:\Temp\memleak\memleak.cpp(15) : {45} normal block at 0x00441BA0, 2 bytes long.
Data: <AB> 41 42
......
Object mp complete.
CRT 庫對程序運行期間分配的所有內存塊進行計數,包括由 CRT 庫自己分配的內存和其它庫(如 MFC)分配的內存。因此,分配序號為 N 的對象即為程序中分配的第 N 個對象,但不一定是代碼分配的第 N 個對象。(大多數情況下並非如此。)
這樣的話,你便可以利用分配序號在分配內存的位置設置一個斷點。方法是在程序起始附近設置一個位置斷點。當程序在該點中斷時,可以從 QuickWatch(快速監視)對話框或 Watch(監視)窗口設置一個內存分配斷點:
例如,在 Watch 窗口中,在 Name 欄鍵入下面的表達式:
_crtBreakAlloc
如果要使用 CRT 庫的多線程 DLL 版本(/MD 選項),那麼必須包含上下文操作符,像這樣:
{,,msvcrtd.dll}_crtBreakAlloc
現在按下回車鍵,調試器將計算該值並把結果放入 Value 欄。如果沒有在內存分配點設置任何斷點,該值將為 –1。
用你想要在其位置中斷的內存分配的分配序號替換 Value 欄中的值。例如輸入 45。這樣就會在分配序號為 45 的地方中斷。
在所感興趣的內存分配處設置斷點後,可以繼續調試。這時,運行程序時一定要小心,要保證內存塊分配的順序不會改變。當程序在指定的內存分配處中斷時,可以查看 Call Stack(調用堆棧)窗口和其它調試器信息以確定分配內存時的情況。如果必要,可以從該點繼續執行程序,以查看對象發生了什麼情況,或許可以確定未正確釋放對象的原因。
盡管通常在調試器中設置內存分配斷點更方便,但如果願意,也可在代碼中設置這些斷點。為了在代碼中設置一個內存分配斷點,可以增加這樣一行(對於第四十五個內存分配):
_crtBreakAlloc = 45;
你還可以使用有相同效果的 _CrtSetBreakAlloc 函數:
_CrtSetBreakAlloc(45);
如何比較內存狀態?
定位內存泄漏的另一個方法就是在關鍵點獲取應用程序內存狀態的快照。CRT 庫提供了一個結構類型 _CrtMemState。你可以用它來存儲內存狀態的快照:
_CrtMemState s1, s2, s3;
若要獲取給定點的內存狀態快照,可以向 _CrtMemCheckpoint 函數傳遞一個 _CrtMemState 結構。該函數用當前內存狀態的快照填充此結構:
_CrtMemCheckpoint( &s1 );
通過向 _CrtMemDumpStatistics 函數傳遞 _CrtMemState 結構,可以在任意地方 mp 該結構的內容:
_CrtMemDumpStatistics( &s1 );
該函數輸出如下格式的 mp 內存分配信息:
0 bytes in 0 Free Blocks.
75 bytes in 3 Normal Blocks.
5037 bytes in 41 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 5308 bytes.
Total allocations: 7559 bytes.
若要確定某段代碼中是否發生了內存泄漏,可以通過獲取該段代碼之前和之後的內存狀態快照,然後使用 _CrtMemDifference 比較這兩個狀態:
_CrtMemCheckpoint( &s1 );// 獲取第一個內存狀態快照
// 在這里進行內存分配
_CrtMemCheckpoint( &s2 );// 獲取第二個內存狀態快照
// 比較兩個內存快照的差異
if ( _CrtMemDifference( &s3, &s1, &s2) )
_CrtMemDumpStatistics( &s3 );// mp 差異結果
顧名思義,_CrtMemDifference 比較兩個內存狀態(前兩個參數),生成這兩個狀態之間差異的結果(第三個參數)。在程序的開始和結尾放置 _CrtMemCheckpoint 調用,並使用 _CrtMemDifference 比較結果,是檢查內存泄漏的另一種方法。如果檢測到泄漏,則可以使用 _CrtMemCheckpoint 調用通過二進制搜索技術來分割程序和定位泄漏。

閱讀全文

與內存泄漏檢測方法相關的資料

熱點內容
有什麼方法治早泄 瀏覽:638
新生兒去黃疸有什麼方法 瀏覽:911
pmt函數的使用方法 瀏覽:782
食用扁粉的十種方法 瀏覽:423
南京競爭對手調研方法有哪些 瀏覽:89
解決腦控的方法 瀏覽:570
籃球網袋簡單編織方法 瀏覽:780
剖腹產放屁的快速方法 瀏覽:747
少兒英語對話教學方法 瀏覽:212
熱天蚊蟲太多有什麼好方法 瀏覽:898
時間靜止時用什麼方法能看到 瀏覽:317
阜陽蒸雞蛋的方法與步驟 瀏覽:486
快速懷孕的最佳方法 瀏覽:370
用手機賺200元的方法 瀏覽:185
角質調理凝露使用方法 瀏覽:964
躁鬱常見治療方法 瀏覽:128
活蝦怎麼去皮最好方法 瀏覽:484
五倍液使用方法 瀏覽:645
怎麼用眼線液使用方法 瀏覽:76
最簡單的塑腿型的方法 瀏覽:155