2012-04-05 153 views
4

我們在我們的應用程序緩慢內存泄漏問題,我已經在試圖analyize對泄漏的原因通過以下步驟已經過去了:調查內存泄漏

  1. 啓用在GFlags在
  2. 用戶模式堆棧跟蹤數據庫
  3. 在WinDbg中,輸入以下命令:堆-stat -h 1250000(其中125萬是具有泄漏堆的地址) 比較多個轉儲之後,我看到大小的存儲器塊位於0xC隨着時間的推移而增加,可能是泄露的內存。
  4. 鍵入以下命令:堆-flt SC 給那些分配和最終的UserPtr:
  5. 打字堆-p -a一些這些地址的地址總是顯示下面的分配調用堆棧:

0:000>堆-p -a 10576ef8

address 10576ef8 found in 
_HEAP @ 1250000 
    HEAP_ENTRY Size Prev Flags UserPtr UserSize - state 
    10576ed0 000a 0000 [03] 10576ef8 0000c - (busy) 
    mscoreei!CLRRuntimeInfoImpl::`vftable' 
    7c94b244 ntdll!RtlAllocateHeapSlowly+0x00000044 
    7c919c0c ntdll!RtlAllocateHeap+0x00000e64 
    603b14a4 mscoreei!UtilExecutionEngine::ClrHeapAlloc+0x00000014 
    603b14cb mscoreei!ClrHeapAlloc+0x00000023 
    603b14f7 mscoreei!ClrAllocInProcessHeapBootstrap+0x0000002e 
    603b1614 mscoreei!operator new[]+0x0000002b 
    603d402b +0x0000005f 
    603d5142 mscoreei!GetThunkUseState+0x00000025 
    603d6fe8 mscoreei!_CorDllMain+0x00000056 
    79015012 mscoree!ShellShim__CorDllMain+0x000000ad 
    7c90118a ntdll!LdrpCallInitRoutine+0x00000014 
    7c919a6d ntdll!LdrpInitializeThread+0x000000c0 
    7c9198e6 ntdll!_LdrpInitialize+0x00000219 
    7c90e457 ntdll!KiUserApcDispatcher+0x00000007 

氏看起來像線程初始化調用堆棧,但我需要知道比這更多。 爲了把手指放在泄漏的確切原因,你會建議做什麼下一步。

回答

2

第一件事是,新的運營商是new []運營商,所以有相應的delete[]電話,而不是一個普通的舊delete呼叫?

如果您懷疑這個代碼,我會把測試工具圍繞它,比如把它放在一個循環,並執行它100或1000倍,它仍泄漏和比例。

您還可以使用進程管理器或編程方式使用GetProcessInformation衡量內存增加。

另一個明顯的一點就是看當你註釋掉調用這個函數會發生什麼,莫非是內存泄漏消失?你可能需要做一個二進制的印章,如果可能的代碼被註釋掉的代碼,但是,改變代碼的行爲可能會導致更多的問題或者相關的代碼路徑問題,這樣可以減少一半(大約)每一次可能的可疑代碼導致內存泄漏或奇怪的行爲。

編輯 忽略以下內容,因爲您在託管環境中工作。

您也可以考慮使用STL或更好,但boost引用計數指針像shared_ptrscoped_array的陣列結構來管理對象的生命週期。

+0

儘管未指定語言,mscoreei!*的存在表明這是一種託管語言,因此需要刪除,使用STL,boost等可能不適用。 – jcopenha 2012-04-05 23:48:02

+0

問題是,這個callstack顯示CLR代碼,而不是我的代碼,所以我不知道在哪裏搜索。 – galbarm 2012-04-06 09:02:56

+0

它看起來像加載一些dll,因爲我看到一個dllmain像打電話,什麼是mscoreei?我不知道任何關於.net的是這個你的dll或第三方,而不是MS .net dll?它是不太可能的一個MS DLL的內存泄漏,所以這可能是由調用代碼的不正確使用,你可以設置一個斷點函數'bp mscoreei!GetThunkUseState',當這被稱爲檢查調用堆棧,並看到如果這給你更多的信息比死後轉儲 – EdChum 2012-04-06 13:50:31

6

使用GFlags時記錄的堆棧不使用.PDB,往往不正確完成。 既然你已經查明泄漏下來在給定的堆特定的大小,你可以嘗試 設置在RtlAllocateHeap現場休息和適當的符號檢查在WinDbg中的堆棧。我已經使用了下面的一些成功。你必須編輯它以適應你的堆和大小。

$$ Display stack if heap handle eq 0x00310000 and size is 0x1303 
$$ ==================================================================== 
bp ntdll!RtlAllocateHeap "j ((poi(@esp+4) = 0x00310000) & (poi(@esp+c) = 0x1303))'k';'gc'" 

也許你會得到另一個堆棧和其他想法的罪犯。