2013-11-14 49 views
2

我有一個內存轉儲文件,似乎是'System.Drawing.Bitmap'對象的內存泄漏。 我有這種類型的多個對象和!gcroot不幫助我確定泄漏的位置。如何從'System.Drawing.Bitmap'中提取圖像以通過windbg文件?

示例輸出:

DOMAIN(0071D148):手柄(銷接):1513e8:根: 03335250(System.Object的[]) - > 0248e8ec(System.Drawing.Bitmap)

我有一個想法,從內存轉儲提取圖像到一個圖像文件,然後,當我可以看到什麼是圖像泄漏,我可以檢查創建該特定位圖周圍的源代碼。

那麼,如何將內存寫入文件中,我可以在圖像查看器中打開並查看Bitmap對象所保存的圖像?另外,如果您有其他想法如何識別泄漏源,我很樂意聽到他們的聲音。

謝謝

回答

5

System.Drawing.Bitmap是一個很小的管理對象。它包裝由非託管GDI + api返回的句柄,存儲在專用nativeImage字段中。從那個手柄中查找位圖數據是乾草堆狩獵活動中的針頭練習。該位圖數據也不以任何方式與圖像文件格式兼容,只有Bitmap :: Save()調用可以執行該操作,運行所需的圖像編碼器。

劃痕這個想法。

具有Bitmap對象的內存問題,否則非常普遍。太多的程序員忽略Bitmap繼承IDisposable。您可以編寫大量的.NET程序,並且永遠不要調用Dispose()或使用語句來使用,並且程序運行良好。垃圾收集器可以避免麻煩。然而,Bitmap類是單一的.NET類,不能再工作了。問題是,它是微小。在觸發垃圾回收之前,您可以創建數以萬計的垃圾回收。幾乎不足以讓垃圾收集器釋放非託管的GDI +句柄。因此,該程序運行很重,使用大量非託管內存。當程序以32位模式運行時,OOM崩潰很可能發生。或64位模式下的千兆字節承諾大小

在Windbg迷路之前,請先仔細閱讀該程序的源代碼。並驗證您可以使用語句將位圖變量與相應的Dispose()調用或配對。注意事項,如分配一個PictureBox.Image屬性,無需調用前一圖像上的Dispose()方法的代碼。 .NET內存分析器否則是更好的調試工具。

+0

感謝您的評論。我正在處理一個非常大的程序,並且很難掃描Bitmap使用的所有位置。這就是爲什麼我通過我的想法可以將我引導到代碼中更具體的地方。 – avivr

+0

這不是一個評論,它是一個答案。最後一句話毫不懷疑,你需要在一個非常大的程序中解決這個問題。記憶分析器顯示大海撈針,那是他們的工作。 –

+0

內存轉儲來自客戶,問題在我的環境中不會重複,因此我無法使用Profiler實時調試它。無論如何,再次感謝您的答案。 – avivr

1

如果你真的想這樣做,似乎仍然有可能dump all bitmaps from memory

步驟:

  1. !dumpheap -short -type System.Drawing.Bitmap
  2. !do <address>
  3. 查找偏移的對IntPtr的財產nativeImage
  4. dps(?等於dps poi(<address>+<offset>))爲您提供了類型
  5. dt <address> <type> - > InternalBitmap屬性
  6. dt <internalAddress> <internalType> - >骨形態發生蛋白財產
  7. dt <bmpAddress> <bmpType>給SCAN0屬性,它是起始地址

我只是無法在如何計算位圖的大小,這將需要做.writemem跟隨。有寬度和高度,可能PixelFormat可能用於計算每像素的位數。

相關問題