2013-10-25 107 views
1

我有一個應用程序的堆損壞崩潰,所以我打開了從gflags的頁堆,並收集該應用程序的故障轉儲文件。堆腐敗雙釋放內存

從轉儲文件中,我發現它是由於雙重釋放內存。

下面是一個例子,從調用堆棧,我發現這個

msvcr100!free(void * pBlock = "**Address**") 

然後我做了這個

!heap -p -a <address> 

address found in 
_HEAP @ 
    HEAP_ENTRY Size Prev Flags UserPtr UserSize - state 
    Address 000a 0000 [02] address 00003 - **(free)** 
Trace: <1> 
     <2> 
     <3> 

所以我們可以看到,它正試圖雙重釋放內存,並且導致在崩潰。我的問題是我們能否在這個操作之前看到更改或釋放內存的調用堆棧?可能嗎?

我可以在!heap -p -a命令下看到一個跟蹤,是釋放內存的那個?如果是這樣,我只能看到調用堆棧的一部分,是否有任何方法可以看到總的調用堆棧或手動遍歷調用堆棧以查看哪個操作釋放了該塊內存。

+0

您所要求的一臺時間機器,轉儲文件沒有一個。 –

+0

是的,我知道轉儲文件在那個時間點是快照,但是如果啓用整頁堆可以提供更多的信息,而不是像誰試圖釋放內存一樣,那些已經釋放內存的人? – user2800803

+0

您應該可以啓用頁堆以使您自己開始 - 頁堆使用位模式標記內存,以便更容易捕獲損壞(如雙重使用)。此外,這個鏈接應該是有幫助的:http://code.msdn.microsoft.com/windowsdesktop/CppHeapCorruption-7a727b6a – deemok

回答

1

如果你有源代碼,你可以用你自己的函數來替換刪除/釋放函數,這些函數可以在發佈實際發生之前捕獲堆棧。

在windows上,您可以使用函數CaptureStackBackTrace獲得調用堆棧,但是此函數會返回一組指針,您需要將它們轉換爲符號名稱。 要做到這一點,您可以使用SymInitialize,然後對於每個指針,您可以使用SymFromAddr來獲取符號的名稱。名稱是您正在搜索的實際功能。

但是,在Windows上使用調試器會更容易。還有Application Verifier這是微軟的一個應用程序,可以幫助您捕獲堆損壞(當與Visual Studio調試器一起使用時)。

希望這會有所幫助 Razvan。

+0

感謝Raxvan,所以在調用堆棧嘗試之前沒有可能檢查釋放內存的函數釋放Windbg中的內存? – user2800803

+0

是的,你需要跟蹤釋放的指針。您可以保留已釋放的指針的一個指針,並且當您再次釋放指針時,如果指針仍然存在,請檢查該指針。在集合內部,您還可以保留該callstack – Raxvan

0

如果您運行調試版本,那麼您很可能會看到更多的調用堆棧。

另見本link