MemoryMappingFile泄漏分析过程
生活随笔
收集整理的這篇文章主要介紹了
MemoryMappingFile泄漏分析过程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近項目突然收到了一個緊急的問題報告 - 用戶在進行某些關鍵操作的時候整個軟件突然就crash掉了。幸好產品繼承了自動抓取dump的功能。。。
收到dump之后,通過windbg打開,查看相應的callstack。迅速定位到出錯的線程。在調用MapViewOfFile()的時候沒有map成功導致crash。 接下來,我們需要知道為什么為何map失敗?通過GetLastErrorCode(),我們得知進程OutOfMemory導致map失敗。MapViewOfFile()需要映射512KB(4Mb)連續內存,而通過!address -summary命令,我們發現系統里最大的連續內存塊為1.5Mb。Crash因此發生了。 至此,我們可以肯定,該crash是由于memory leak造成MapViewOfFile()失敗。那么,是什么leak了?重新看上面的輸出信息,我們可以看到,MEM_MAPPED使用的內存高達934Mb,MEM_PRIVATE使用的內存為805Mb。據此,我們懷疑,產品里所使用的memory mapped file可能會存在大量的leak。 運行命令!address -f:MEM_MAPPED,會得到類似的輸出: 第三列,也就是RgnSize,為當前MMF的映射窗口大小。查看了該輸出,我們發現,窗口大小為512kB的文件在500個左右,而大小為256KB的文件多大1800個。據此,我們可以鎖定這些256KB的MMF文件。 下面的問題,就是,誰映射了這么多的MMF文件?在此不同的項目可以有不同的方法。如果你很熟悉項目數據的話,你可以先通過dd查看一下該256KB的內容都是啥?有沒有你所熟悉的內容?如果是字符串的話那就更容易定位問題的所在地方了。 這里,我們假設我們不熟悉文件的內容,從而無法猜測這些數據是誰產生的。我們只能采取其他辦法。 上面輸出的第一列,也就是BaseAddr,為該map view的地址。如果我們要使用該map view的話,我們必須要有對應的指針指向該view。因此,我們隨機選了一個256KB的view的baseaddress,然后通過下面的命令查找誰還指向了這塊內存。 從該輸出我們能夠看到,大概有10多個地方保存有該指針地址。接下來,我們就需要查看誰,也就是那些類的instance還保存這些地址。此處沒有其他好的辦法,只能在這些地址四處通過dds命令來查看是否有對象的symbol。 在查看了多個地址之后,我們發現,有一個vftable為CMMFSerializer的對象。這給了我們極大的肯定:該類名里有MMF!十有八九是該類的leak! 接下來,我們的目標為誰創建了CMMFSerializer對象而沒有銷毀?首先,我們通過x命令來獲得CMMFSerializer的虛表地址,這樣我們就能夠在heap里搜索這些對象都存在哪里。 然后,運行!heap命令,就能夠查看到擁有這些對象的地址了。 從我們的輸出能夠看到,大量的CommunicatorObj對象存在heap里。這就說明了CommunicatorObj這些對象沒有被刪除掉。從而,我們可以做這樣的結論:CommunicatorObj的泄漏導致了如此之多的MMF的泄漏,以及很高的MMF_PRIVATE使用率如此之高。剩下來的工作就很簡單了,看看代碼,分析分析哪些地方使用了CommunicatorObj。轉載于:https://www.cnblogs.com/xiaxi/p/3719263.html
總結
以上是生活随笔為你收集整理的MemoryMappingFile泄漏分析过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【HDOJ】1239 Calling E
- 下一篇: NIO入门系列之第3章:从理论到实践:N