2

「System.Drawing.Bitmap」オブジェクトのメモリ リークと思われるメモリ ダンプ ファイルがあります。そのタイプのオブジェクトが複数あり、!gcroot はリークの場所を特定するのに役立ちません。

出力例:

ドメイン (0071D148):ハンドル (固定):1513e8:ルート: 03335250 (System.Object[])-> 0248e8ec (System.Drawing.Bitmap)

メモリ ダンプから画像を画像ファイルに抽出するというアイデアがありました。その後、リークしている画像が何であるかを確認できたら、その特定のビットマップの作成を囲むソース コードを調べることができました。

では、画像ビューアで開いて Bitmap オブジェクトが保持する画像を表示できるファイルにメモリを書き込むにはどうすればよいでしょうか?

また、リーク元を特定する方法について他にアイデアがあれば、喜んで伺います。

ありがとう

4

2 に答える 2

5

System.Drawing.Bitmap は小さなマネージド オブジェクトです。これは、アンマネージ GDI+ API によって返され、プライベートのnativeImageフィールドに格納されたハンドルをラップします。そのハンドルからビットマップ データを見つけることは、干し草の山を探す練習です。また、そのビットマップ データは画像ファイル形式と互換性がありません。Bitmap::Save() 呼び出しだけがそれを行うことができ、必要な画像エンコーダーを実行します。

このアイデアをスクラッチします。

それ以外の場合、Bitmap オブジェクトでメモリの問題が発生することは非常に一般的です。Bitmap が IDisposable を継承していることを無視しているプログラマが多すぎます。多くの .NET プログラムを記述できますが、一度も Dispose() を呼び出したり、usingステートメントを使用したりすることはなく、プログラムは正常に実行されます。ガベージ コレクターは、それらをトラブルから守ります。ただし、Bitmap クラスは、もは​​や機能しない単一の .NET クラスです。問題は、それが小さいことです。ガベージ コレクションをトリガーする前に、何万ものそれらを作成できます。ほとんどの場合、ガベージ コレクターがアンマネージ GDI+ ハンドルを解放するのに十分ではありません。その結果、プログラムは非常に実行されます大量のアンマネージ メモリを使用します。プログラムが 32 ビット モードで実行されると、OOM クラッシュが発生する可能性が非常に高くなります。または、64 ビット モードでギガバイトのコミット サイズ

Windbg で迷子になる前に、まずプログラムのソース コードを注意深く確認してください。また、すべての Bitmap 変数を、対応する Dispose() 呼び出しまたはusingステートメントとペアにできることを確認します。前の画像で Dispose() メソッドを呼び出すコードなしで PictureBox.Image プロパティを割り当てるなどのことには注意してください。それ以外の場合、.NET メモリ プロファイラーは、これをデバッグするための優れたツールです。

于 2013-11-14T11:46:03.220 に答える
1

It seems still possible to dump all bitmaps from memory, if you really want to do it.

The steps:

  1. !dumpheap -short -type System.Drawing.Bitmap
  2. !do <address>
  3. Find offset of property nativeImage
  4. dps on that IntPtr (equal to dps poi(<address>+<offset>) ?) gives you the type
  5. dt <address> <type> --> InternalBitmap property
  6. dt <internalAddress> <internalType> --> Bmp property
  7. dt <bmpAddress> <bmpType> gives Scan0 property, which is the start address

I just couldn't follow on how to calculate the size of the bitmap, which would be needed to do a .writemem. There is width and height and probably PixelFormat could be used to calculate the bits per pixel.

于 2014-01-18T21:34:55.437 に答える