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

騰訊內存泄漏檢測方法專利

發布時間:2022-08-07 08:52:18

如何檢測DLL中的內存泄漏

可以直接騰訊電腦管家查殺
操作起來也很簡便的,查殺木馬病毒也很快速哦!我們安裝登錄後在主頁面最下面找到第二個快捷功能鍵,點擊進入就可以享受到它強大的查殺效果啦。右上角還有輕巧模式和傳統模式相互切換的鍵呢,我們可以選擇自己喜歡的操作界面哦!

Ⅱ 如何定位內存泄漏問題

內存泄漏指由於疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。
這是C和C++程序員的噩夢之一。
1)實質:
內存泄漏並非指內存在物理上的消失,而是應用程序分配某段內存後,由於設計錯誤,導致在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費;
2)原理:
內存泄露的關鍵就是記錄分配的內存和釋放內存的操作,看看能不能匹配。跟蹤每一塊內存的生命周期;
3)方法:不同開發環境有不同的檢測方法,下面以VisualStudio為例介紹。
在VS中使用時,需加上
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
crtdbg.h的作用是將malloc和free函數映射到它們的調試版本_malloc_dbg和_free_dbg,這兩個函數將跟蹤內存分配和釋放(在Debug版本中有效)
_CrtDumpMemoryLeaks();
函數將顯示當前內存泄露,也就是說程序運行到此行代碼時的內存泄露,所有未銷毀的對象都會報出內存泄露,因此要讓這個函數盡量放到最後。

Ⅲ 如何檢查內存泄露問題

簡單說明了一下沒有工具的情況如何運用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的提供的檢查工具也不太少,但是如果是棧出了什麼問題,恐怕就麻煩很多了。棧出問題,一般不會產生內存泄漏,但是你的代碼的邏輯上很有可能會有影響。這個是最最痛苦的事情。 編程,就是小心,小心再小心而已。

Ⅳ 如何用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)

就是源文件名稱和行號。

Ⅳ 如何測試一個軟體是否內存泄漏,怎麼測試具體點,各位大俠們!!!

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系列的一個插件。

Ⅵ 怎麼排查這些內存泄漏

最原始的內存泄露測試
重復多次操作關鍵的可疑的路徑,從內存監控工具中觀察內存曲線,是否存在不斷上升的趨勢且不會在程序返回時明顯回落。
這種方式可以發現最基本,也是最明顯的內存泄露問題,對用戶價值最大,操作難度小,性價比極高。
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的質量情況,及時機型修改。目前騰訊內部所有的產品,均在使用其進行線上產品的崩潰監控。

Ⅶ 如何檢測內存泄漏

靈活自由是C/C++語言的一大特色,而這也為C/C++程 序員出了一個難題。當程序越來越復雜時,內存的管理也會變得越加復雜,稍有不慎就會出現內存問題。內存泄漏是最常見的內存問題之一。內存泄漏如果不是很嚴 重,在短時間內對程序不會有太大的影響,這也使得內存泄漏問題有很強的隱蔽性,不容易被發現。然而不管內存泄漏多麼輕微,當程序長時間運行時,其破壞力是 驚人的,從性能下降到內存耗盡,甚至會影響到其他程序的正常運行。另外內存問題的一個共同特點是,內存問題本身並不會有很明顯的現象,當有異常現象出現時 已時過境遷,其現場已非出現問題時的現場了,這給調試內存問題帶來了很大的難度。

Visual Leak Detector是一款用於Visual C++的免費的內存泄露檢測工具。相比較其它的內存泄露檢測工具,它在檢測到內存泄漏的同時,還具有如下特點:
1、 可以得到內存泄漏點的調用堆棧,如果可以的話,還可以得到其所在文件及行號;
2、 可以得到泄露內存的完整數據;
3、 可以設置內存泄露報告的級別;
4、 它是一個已經打包的lib,使用時無須編譯它的源代碼。而對於使用者自己的代碼,也只需要做很小的改動;
5、 他的源代碼使用GNU許可發布,並有詳盡的文檔及注釋。對於想深入了解堆內存管理的讀者,是一個不錯的選擇。

可見,從使用角度來講,Visual Leak Detector簡單易用,對於使用者自己的代碼,唯一的修改是#include Visual Leak Detector的頭文件後正常運行自己的程序,就可以發現內存問題。從研究的角度來講,如果深入Visual Leak Detector源代碼,可以學習到堆內存分配與釋放的原理、內存泄漏檢測的原理及內存操作的常用技巧等。

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

很高興為您解答。

怎樣檢測內存泄露 :

檢測內存泄漏的關鍵是要能截獲住對分配內存和釋放內存的函數的調用。截獲住這兩個函數,我們就能跟蹤每一塊內存的生命周期,比如,每當成功的分配一塊內存後,就把它的指針加入一個全局的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雖然無法標示出發生問題的代碼,但是它能檢測出隱式的內存泄漏的存在,這是其他兩類工具無能為力的地方。

Ⅸ Visual Leak Detector 內存泄露檢測,該怎麼處理

在實現過程中,也有點拿不穩,特別是用隊列或棧來存儲樹的結點(也是指針)時,為了確保沒問題,特別是內存的分配,我搜索並安裝了Virtual Leak Detector,一個開源的內存泄漏檢測工具。
初識Visual Leak Detector
靈活自由是C/C++語言的一大特色,而這也為C/C++程 序員出了一個難題。當程序越來越復雜時,內存的管理也會變得越加復雜,稍有不慎就會出現內存問題。內存泄漏是最常見的內存問題之一。內存泄漏如果不是很嚴 重,在短時間內對程序不會有太大的影響,這也使得內存泄漏問題有很強的隱蔽性,不容易被發現。然而不管內存泄漏多麼輕微,當程序長時間運行時,其破壞力是 驚人的,從性能下降到內存耗盡,甚至會影響到其他程序的正常運行。另外內存問題的一個共同特點是,內存問題本身並不會有很明顯的現象,當有異常現象出現時 已時過境遷,其現場已非出現問題時的現場了,這給調試內存問題帶來了很大的難度。< xmlnamespace prefix ="o" />

Visual Leak Detector是一款用於Visual C++的免費的內存泄露檢測工具。可以在http://www.codeproject.com/tools/visualleakdetector.asp 下載到。相比較其它的內存泄露檢測工具,它在檢測到內存泄漏的同時,還具有如下特點:
1、 可以得到內存泄漏點的調用堆棧,如果可以的話,還可以得到其所在文件及行號;
2、 可以得到泄露內存的完整數據;
3、 可以設置內存泄露報告的級別;
4、 它是一個已經打包的lib,使用時無須編譯它的源代碼。而對於使用者自己的代碼,也只需要做很小的改動;
5、 他的源代碼使用GNU許可發布,並有詳盡的文檔及注釋。對於想深入了解堆內存管理的讀者,是一個不錯的選擇。

可見,從使用角度來講,Visual Leak Detector簡單易用,對於使用者自己的代碼,唯一的修改是#include Visual Leak Detector的頭文件後正常運行自己的程序,就可以發現內存問題。從研究的角度來講,如果深入Visual Leak Detector源代碼,可以學習到堆內存分配與釋放的原理、內存泄漏檢測的原理及內存操作的常用技巧等。
本文首先將介紹Visual Leak Detector的使用方法與步驟,然後再和讀者一起初步的研究Visual Leak Detector的源代碼,去了解Visual Leak Detector的工作原理。
< xmlnamespace prefix ="v" />
使用Visual Leak Detector(1.0)
下面讓我們來介紹如何使用這個小巧的工具。
首先從網站上下載zip包,解壓之後得到vld.h, vldapi.h, vld.lib, vldmt.lib, vldmtdll.lib, dbghelp.dll等文件。將.h文件拷貝到Visual C++的默認include目錄下,將.lib文件拷貝到Visual C++的默認lib目錄下,便安裝完成了。因為版本問題,如果使用windows 2000或者以前的版本,需要將dbghelp.dll拷貝到你的程序的運行目錄下,或其他可以引用到的目錄。
註:我下載的是較新版1.9,直接安裝到系統中。因此使用時必須先在VC中設置一下目錄。

接下來需要將其加入到自己的代碼中。方法很簡單,只要在包含入口函數的.cpp文件中包含vld.h就可以。如果這個cpp文件包含了stdafx.h,則將包含vld.h的語句放在stdafx.h的包含語句之後,否則放在最前面。如下是一個示常式序:
#include <vld.h>
void main()
{

}
接下來讓我們來演示如何使用Visual Leak Detector檢測內存泄漏。下面是一個簡單的程序,用new分配了一個int大小的堆內存,並沒有釋放。其申請的內存地址用printf輸出到屏幕上。

編譯運行後,在標准輸出窗口得到:
p=003a89c0

在Visual C++的Output窗口得到:

WARNING: Visual Leak Detector detected memory leaks!
---------- Block 57 at 0x003A89C0: 4 bytes ---------- --57號塊0x003A89C0地址泄漏了4個位元組
Call Stack: --下面是調用堆棧
d:/test/testvldconsole/testvldconsole/main.cpp (7): f --表示在main.cpp第7行的f()函數
d:/test/testvldconsole/testvldconsole/main.cpp (14): main –雙擊以引導至對應代碼處
f:/rtm/vctools/crt_bld/self_x86/crt/src/crtexe.c (586): __tmainCRTStartup
f:/rtm/vctools/crt_bld/self_x86/crt/src/crtexe.c (403): mainCRTStartup
0x7C816D4F (File and line number not available): RegisterWaitForInputIdle
Data: --這是泄漏內存的內容,0x12345678
78 56 34 12 xV4..... ........

Visual Leak Detector detected 1 memory leak.
第二行表示57號塊有4位元組的內存泄漏,地址為0x003A89C0,根據程序控制台的輸出,可以知道,該地址為指針p。程序的第7行,f()函數里,在該地址處分配了4位元組的堆內存空間,並賦值為0x12345678,這樣在報告中,我們看到了這4位元組同樣的內容。
可以看出,對於每一個內存泄漏,這個報告列出了它的泄漏點、長度、分配該內存時的調用堆棧、和泄露內存的內容(分別以16進制和文本格式列出)。雙擊該堆棧報告的某一行,會自動在代碼編輯器中跳到其所指文件的對應行。這些信息對於我們查找內存泄露將有很大的幫助。
這是一個很方便易用的工具,安裝後每次使用時,僅僅需要將它頭文件包含進來重新build就可以。而且,該工具僅在build Debug版的時候會連接到你的程序中,如果build Release版,該工具不會對你的程序產生任何性能等方面影響。所以盡可以將其頭文件一直包含在你的源代碼中。
Visual Leak Detector工作原理
下面讓我們來看一下該工具的工作原理。
在這之前,我們先來看一下Visual C++內置的內存泄漏檢測工具是如何工作的。Visual C++內置的工具CRT Debug Heap工作原來很簡單。在使用Debug版的malloc分配內存時,malloc會在內存塊的頭中記錄分配該內存的文件名及行號。當程序退出時CRT會在main()函數返回之後做一些清理工作,這個時候來檢查調試堆內存,如果仍然有內存沒有被釋放,則一定是存在內存泄漏。從這些沒有被釋放的內存塊的頭中,就可以獲得文件名及行號。
這種靜態的方法可以檢測出內存泄漏及其泄漏點的文件名和行號,但是並不知道泄漏究竟是如何發生的,並不知道該內存分配語句是如何被執行到的。要想了解這些,就必須要對程序的內存分配過程進行動態跟蹤。Visual Leak Detector就是這樣做的。它在每次內存分配時將其上下文記錄下來,當程序退出時,對於檢測到的內存泄漏,查找其記錄下來的上下文信息,並將其轉換成報告輸出。

初始化
Visual Leak Detector要記錄每一次的內存分配,而它是如何監視內存分配的呢?Windows提供了分配鉤子(allocation hooks)來監視調試堆內存的分配。它是一個用戶定義的回調函數,在每次從調試堆分配內存之前被調用。在初始化時,Visual Leak Detector使用_CrtSetAllocHook注冊這個鉤子函數,這樣就可以監視從此之後所有的堆內存分配了。
如何保證在Visual Leak Detector初始化之前沒有堆內存分配呢?全局變數是在程序啟動時就初始化的,如果將Visual Leak Detector作為一個全局變數,就可以隨程序一起啟動。但是C/C++並沒有約定全局變數之間的初始化順序,如果其它全局變數的構造函數中有堆內存分配,則可能無法檢測到。Visual Leak Detector使用了C/C++提供的#pragma init_seg來在某種程度上減少其它全局變數在其之前初始化的概率。根據#pragma init_seg的定義,全局變數的初始化分三個階段:首先是compiler段,一般c語言的運行時庫在這個時候初始化;然後是lib段,一般用於第三方的類庫的初始化等;最後是user段,大部分的初始化都在這個階段進行。Visual Leak Detector將其初始化設置在compiler段,從而使得它在絕大多數全局變數和幾乎所有的用戶定義的全局變數之前初始化。

記錄內存分配
一個分配鉤子函數需要具有如下的形式:
int YourAllocHook( int allocType, void *userData, size_t size, int blockType, long requestNumber, const unsignedchar *filename, int lineNumber);
就像前面說的,它在Visual Leak Detector初始化時被注冊,每次從調試堆分配內存之前被調用。這個函數需要處理的事情是記錄下此時的調用堆棧和此次堆內存分配的唯一標識——requestNumber。
得到當前的堆棧的二進製表示並不是一件很復雜的事情,但是因為不同體系結構、不同編譯器、不同的函數調用約定所產生的堆棧內容略有不同,要解釋堆棧並得到整個函數調用過程略顯復雜。不過windows提供一個StackWalk64函數,可以獲得堆棧的內容。StackWalk64的聲明如下:
BOOL StackWalk64(
DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetMoleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);

STACKFRAME64結構表示了堆棧中的一個frame。給出初始的STACKFRAME64,反復調用該函數,便可以得到內存分配點的調用堆棧了。
// Walk the stack.
while (count < _VLD_maxtraceframes) {
count++;
if (!pStackWalk64(architecture, m_process, m_thread, &frame, &context,
NULL, pSymFunctionTableAccess64, pSymGetMoleBase64, NULL)) {
// Couldn't trace back through any more frames.
break;
}
if (frame.AddrFrame.Offset == 0) {
// End of stack.
break;
}

// Push this frame's program counter onto the provided CallStack.
callstack->push_back((DWORD_PTR)frame.AddrPC.Offset);
}
那麼,如何得到初始的STACKFRAME64結構呢?在STACKFRAME64結構中,其他的信息都比較容易獲得,而當前的程序計數器(EIP)在x86體系結構中無法通過軟體的方法直接讀取。Visual Leak Detector使用了一種方法來獲得當前的程序計數器。首先,它調用一個函數,則這個函數的返回地址就是當前的程序計數器,而函數的返回地址可以很容易的從堆棧中拿到。下面是Visual Leak Detector獲得當前程序計數器的程序:
#if defined(_M_IX86) || defined(_M_X64)
#pragma auto_inline(off)
DWORD_PTR VisualLeakDetector::getprogramcounterx86x64 ()
{
DWORD_PTR programcounter;

__asm mov AXREG, [BPREG + SIZEOFPTR] // Get the return address out of the current stack frame
__asm mov [programcounter], AXREG // Put the return address into the variable we'll return

return programcounter;
}
#pragma auto_inline(on)
#endif // defined(_M_IX86) || defined(_M_X64)
得到了調用堆棧,自然要記錄下來。Visual Leak Detector使用一個類似map的數據結構來記錄該信息。這樣可以方便的從requestNumber查找到其調用堆棧。分配鉤子函數的allocType參數表示此次堆內存分配的類型,包括_HOOK_ALLOC, _HOOK_REALLOC, 和 _HOOK_FREE,下面代碼是Visual Leak Detector對各種情況的處理。

switch (type) {
case _HOOK_ALLOC:
visualleakdetector.hookmalloc(request);
break;

case _HOOK_FREE:
visualleakdetector.hookfree(pdata);
break;

case _HOOK_REALLOC:
visualleakdetector.hookrealloc(pdata, request);
break;

default:
visualleakdetector.report("WARNING: Visual Leak Detector: in allochook(): Unhandled allocation type (%d)./n", type);
break;
}
這里,hookmalloc()函數得到當前堆棧,並將當前堆棧與requestNumber加入到類似map的數據結構中。hookfree()函數從類似map的數據結構中刪除該信息。hookrealloc()函數依次調用了hookfree()和hookmalloc()。

檢測內存泄露
前面提到了Visual C++內置的內存泄漏檢測工具的工作原理。與該原理相同,因為全局變數以構造的相反順序析構,在Visual Leak Detector析構時,幾乎所有的其他變數都已經析構,此時如果仍然有未釋放之堆內存,則必為內存泄漏。
分配的堆內存是通過一個鏈表來組織的,檢查內存泄漏則是檢查此鏈表。但是windows沒有提供方法來訪問這個鏈表。Visual Leak Detector使用了一個小技巧來得到它。首先在堆上申請一塊臨時內存,則該內存的地址可以轉換成指向一個_CrtMemBlockHeader結構,在此結構中就可以獲得這個鏈表。代碼如下:
char *pheap = new char;
_CrtMemBlockHeader *pheader = pHdr(pheap)->pBlockHeaderNext;
delete pheap;
其中pheader則為鏈表首指針。

報告生成
前面講了Visual Leak Detector如何檢測、記錄內存泄漏及其其調用堆棧。但是如果要這個信息對程序員有用的話,必須轉換成可讀的形式。Visual Leak Detector使用SymGetLineFromAddr64()及SymFromAddr()生成可讀的報告。
// Iterate through each frame in the call stack.
for (frame = 0; frame < callstack->size(); frame++) {
// Try to get the source file and line number associated with
// this program counter address.
if (pSymGetLineFromAddr64(m_process,
(*callstack)[frame], &displacement, &sourceinfo)) {
...
}

// Try to get the name of the function containing this program
// counter address.
if (pSymFromAddr(m_process, (*callstack)[frame],
&displacement64, pfunctioninfo)) {
functionname = pfunctioninfo->Name;
}
else {
functionname = "(Function name unavailable)";
}
...
}
概括講來,Visual Leak Detector的工作分為3步,首先在初始化注冊一個鉤子函數;然後在內存分配時該鉤子函數被調用以記錄下當時的現場;最後檢查堆內存分配鏈表以確定是否存在內存泄漏並將泄漏內存的現場轉換成可讀的形式輸出。有興趣的讀者可以閱讀Visual Leak Detector的源代碼。

總結
在使用上,Visual Leak Detector簡單方便,結果報告一目瞭然。在原理上,Visual Leak Detector針 對內存泄漏問題的特點,可謂對症下葯——內存泄漏不是不容易發現嗎?那就每次內存分配是都給記錄下來,程序退出時算總賬;內存泄漏現象出現時不是已時過境 遷,並非當時泄漏點的現場了嗎?那就把現場也記錄下來,清清楚楚的告訴使用者那塊泄漏的內存就是在如何一個調用過程中泄漏掉的。
Visual Leak Detector是一個簡單易用內存泄漏檢測工具。現在最新的版本是1.9a,採用了新的檢測機制,並在功能上有了很多改進。不妨體驗一下

Ⅹ 內存泄露有哪些方法定位,崩潰有哪些方法定位

ios怎麼查看內存泄露,有以下幾種方法供大家參考:

  1. 靜態分析

  2. 通過靜態分析我們可以最初步的了解到代碼的一些不規范的地方或者是存在的內存泄漏,這是我們第一步對內存泄漏的檢測。當然有一些警告並不是我們關心的可以略過。

  3. 2.通過instruments來檢查內存泄漏

  4. 這個方法能粗略的定位我們在哪裡發生了內存泄漏。方法是完成一個循環操作,如果內存增長為0就證明我們程序在該次循環操作中不存在內存泄漏,如果內存增長不為0那證明有可能存在內存泄漏,當然具體問題需要具體分析。

  5. 3.代碼測試內存泄漏

  6. 在做這項工作之前我們要注意一下,在dealloc的方法中我們是否已經釋放了該對象所擁有的所有對象。觀察對象的生成和銷毀是否配對。准確的說就是init(創建對象的方法)和dealloc是否會被成對觸發(簡單說來就是走一次創建對象就有走一次dealloc該對象)。

  7. 下面是自己遇到的一些比較隱秘的造成內存泄漏的情況:

  8. 1.兩個對象互相擁有:也就是說對象a裡面retain/addSubview了b對象,b對象同時也retain/addSubView了a對象。注意:delegate不要用retain屬性,要用assign屬性也會導致互相擁有。

  9. 2.有時候需要用removeFromSuperView來釋放:具體說明,也許我的a對象擁有一個b對象,b對象add到了c對象上,而在我們的設計中b對象的生命周期應該和a對象相同;這時候只一句[b release]/self.b = nil是不能把b對象釋放掉的(一般情況下release會使其retainCount-1,[super dealloc]會再次將所有subView的retainCount-1,而b並不是a的subView,所有最後的一次-1沒有了);所以我們需要在之前加上[b removeFromSuperView]。

閱讀全文

與騰訊內存泄漏檢測方法專利相關的資料

熱點內容
m6藍牙連接方法 瀏覽:228
花椒都是有什麼用處及服用方法 瀏覽:530
如何用洗衣服的方法去靜電妙招 瀏覽:332
移動數據線頭連接方法 瀏覽:887
手機網路很卡怎麼辦最快的方法 瀏覽:244
gta5拍照截圖在哪裡設置方法 瀏覽:681
橋梁檢測的工作方法 瀏覽:341
生動有趣的教學方法起到什麼效果 瀏覽:119
雙線隔珠打結方法視頻 瀏覽:792
高一怎麼學好物理方法技巧 瀏覽:8
種豆角方法圖片 瀏覽:461
cameraraw使用方法 瀏覽:957
144除以16的簡便計算方法 瀏覽:651
如何用簡單的方法挖出水 瀏覽:138
實驗教學法是研究方法嗎 瀏覽:162
自己檢測肺活量的方法 瀏覽:500
淘寶客的使用方法 瀏覽:942
迷你世界怎麼找到水的方法 瀏覽:337
小孩咳嗽有痰支氣管炎解決方法 瀏覽:234
全網推廣方法有哪些正規專業公司 瀏覽:241