2010-08-25 51 views
8

我想在Windows中檢測C++程序的內存泄漏。 我在MSDN上也閱讀了關於mermoy leak detection的文檔,我也開始使用Visual Leak Detector。使用/不使用Visual Leak Detector的C++中的內存泄漏檢測

我對泄漏的報道有疑問。 我期待一個帶有行號的文件名,但我總是報告下面的文本。 除了文件名和行號以外,它具有泄漏描述(塊類型,內存地址,數據等)的所有組件。 。

如果是真正的泄漏? 如果是,你知道爲什麼文件/行不報告? 在此期間,我在看看還在this url

感謝

 
Detected memory leaks! 
Dumping objects -> 
{4723} normal block at 0x04AFB5B8, 8 bytes long. 
Data: 2C 3F 00 00 28 3F 00 00 
{1476} normal block at 0x04AC3B58, 12 bytes long. 
Data: 00 CD CD CD EB 01 75 4C CA 3D 0B 00 
Object dump complete. 
+0

http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml – DumbCoder 2010-08-25 09:58:07

+0

這是題外話題,但我之前曾建議使用智能指針來避免手動內存管理和內存泄漏 – Ahmed 2010-08-25 11:07:20

+0

您應該使用deleaker。它必須幫助你。 – 2011-12-21 20:11:11

回答

0

你應該使用Valgrind,這是非常強大的,並解釋了正確的地方位於你的程序中的漏洞。你的程序可能需要用gcc編譯,儘管...

+0

我知道這個工具,但恐怕我必須堅持VC++! :) – user311906 2010-08-25 10:32:10

+0

沒有什麼能阻止你在gcc中構建它,儘管泄漏是相同的,無論編譯器 – Patrick 2010-08-25 13:28:32

+3

假設他使用的應用程序+庫與linux/gcc和windows/vC++都兼容 – 2010-09-26 09:11:04

5

這是Visual Studio自己的調試CRT的輸出,而不是來自Visual Leak Detector的輸出。首先確保你使用的是當前版本Codeplex,並且你的項目中包含了#include vld.h。你會得到更多的信息輸出。

+0

嗨mandrill!不幸的是Visual Leak Detector的輸出。我使用的是從CodeProject網站獲取的舊版本,而不是CODEPLEX的版本..所以我認爲我應該更新+我將檢查設置。 重要提示: 你能否輕輕地證實我寫的是真正的泄漏? – user311906 2010-08-25 10:41:41

+0

這不是Visual Leak Detector的輸出 - 您將通過分配對象的調用位置獲得大量輸出。您正在看到Visual Studio泄漏檢測器的輸出:http://msdn.microsoft.com/en-us/library/e5ewb1h3%28VS.80%29.aspx – 2010-08-25 12:02:48

0

Rational Purify可用作VC++的for-money插件,並且是一個非常好的泄漏(以及其他麻煩)檢測器。我曾經在Solaris上使用它很多,它很容易使用和清除。我也聽到了其他人關於用於Visual Studio的版本的好消息,但我從未真正嘗試過。

FWIW,我懷疑Purify是Valgrind的靈感,這已經被提及。

0

如果分配數字(捲曲大括號中的數字)總是相同的,this could help。基本上,它描述瞭如何在嘗試使用指定編號的分配時使VC++生成斷點。

+0

Hi SpaceComboy,謝謝!我注意到了;我發現在某些項目中,它保持不變,還有其他更改。 – user311906 2010-08-25 11:15:47

+0

@ user311906:分配數字只是計算所有的堆分配。如果您的應用程序每次都以相同的順序進行分配,那麼泄漏分配的數量不會發生變化,您可以使用它來追蹤問題的來源。這比文件和行號更有用,因爲它也會給你當前的應用程序狀態。 – 2010-08-25 11:27:14

7

我調查了很多不同的跟蹤內存泄漏的方法。他們都有自己的優勢,但也有缺點。

要了解自己的優點和缺點,我們要了解不同的機制和要求:

  1. 如何新建,刪除,malloc和free攔截?一些工具使用#define重新定義新的,刪除,malloc和空閒的,但是這依賴於include文件的正確順序,並且如果一個類包含例如一種稱爲free的方法(就像Qt中的情況)。預處理器也將重新定義這種方法,這可能會導致編譯錯誤或未解決的外部問題。

    另一種方法是否決全局新的和刪除操作符。這是一個更清潔的解決方案,但是失敗的是你有一個第三方庫,它會在庫中放入一個新的庫,但是在頭中刪除(反之亦然)。

  2. 呼叫的來源是如何確定的。如果新增,刪除...被使用#define攔截,通常使用預處理器符號__FILE____LINE__來獲取泄漏源。但是,如果您在代碼中具有「通用」功能,例如CreateString(),那麼大部分的泄漏將會在這些泛型函數中被報告,這對你並沒有什麼幫助。

    另一種方法是在運行時獲取調用堆棧。使用Windows StackWalk函數可以很容易地完成,但以我的經驗來看,這非常慢。更快的選擇是直接獲取基指針,並依賴棧幀指針(必須使用/ Oy-編譯才能獲取堆棧幀指針)。您可以像這樣獲取幀(基本)指針:_asm mov DWORD PTR [FramePtr], ebp。然後簡單地循環並在循環中獲得來自((ADDR *)FramePtr)[1];的指令指針和來自FramePtr = ((ADDR *)FramePtr)[0];的下一個幀指針

  3. 如何在確切時刻報告泄漏。就我而言,我希望在應用程序結束時報告泄漏,但爲了能夠做到這一點,您需要在應用程序結束時使用泄漏報告機制。這意味着如果你想自己報告你的泄漏,你需要依賴全局變量在應用程序的最後被破壞(並且報告全局變量的析構函數中的泄漏)。對於服務器類型的應用程序,您可能更感興趣的是在兩個時間點之間獲得內存使用量的差異。

而現在不同泄漏系統:

  1. C運行時:在結束報告泄漏,但報告的調用堆棧沒有體面的方式。它攔截呼叫新的,刪除,...的方法可能會導致問題與第三方庫(如Qt,Boost,...)

  2. 外部Microsoft實用程序(如GFlags,UMDH ,, ... ):他們似乎只能記錄兩個時間點之間的差異。但是,調用堆棧看起來好多了,但GFlags實用程序可能會在操作系統中設置標誌,這可能會導致應用程序的嚴重減速。

  3. 視覺泄漏檢測器。似乎正確地找到所有泄漏,但在我的情況下,它不起作用,因爲我有一個第三方DLL,它簡單地中止它的DllUnload進程(似乎是Windows 7的特定問題)。

  4. 我個人最喜歡的(人們不會同意我的說法,我敢肯定),就是寫自己的內存管理器。使用全局新的和刪除操作符(可能存在上面提到的問題)可以輕鬆地進行攔截,並且可以按照上述方法獲取調用堆棧。此替代方案也依賴於能夠在應用程序的最後時刻執行代碼。

當選擇的替代方案,我發現了以下幾個方面對我的情況非常項重要的:

  • 我希望它在我的應用程序無縫工作,讓每一個開發人員會立即通知,如果有一個泄漏。如果您延遲泄漏檢查到稍後使用外部實用程序(如Purify)的時間,泄漏檢測將會更加困難。
  • 我想在應用程序結束時自動報告泄漏。
  • 我想盡可能從泄漏可能的信息(數據,調用棧,...)

希望這有助於。

2

好的。調試了很多頭文件之後,我得到了它。

這裏是什麼,有許多工作要做,以使輸出文件/行號

「的#define _CRTDBG_MAP_ALLOC」

「的#define _CRTDBG_MAP_ALLOC_NEW」

+0

由於某些原因,這兩個定義只是告訴我: c:\ program files(x86)\ microsoft visual studio 10.0 \ vc \ include \ crtdbg.h(1116):{640} 0x000A5E28正常區塊,12個字節長。 除了泄漏...它並沒有真正的幫助 – 2010-09-23 15:56:15

+0

設置這會觸發此警告:c:\ program files \ microsoft visual studio 9.0 \ vc \ include \ crtdbg.h(1203):warning C4985:'operator new' :以前的聲明中不存在的屬性 – Arthur 2012-06-19 10:44:42

1

你調試啓用信息編譯並確保泄漏檢測器可以使用pdb文件?沒有這些信息,它將無法提供行號。