2

特定のマシンで OutOfMemoryExceptions が発生している NUnit テストのテストがあります。

調査の結果、これはメモリの問題ではなく、Handle の問題であると思われます (Bitmap オブジェクトを割り当てすぎて解放していません)。

問題は、これが特定のマシンで完全に実行され、別のマシンでこのエラーで失敗することです。

  1. 失敗したマシンは、Windows7 x64 (6 GB RAM) を搭載した Hyper-V VM です。
  2. 作業マシンは、Windows XP (2 GB RAM) の物理マシンです。

コードをクリーンアップして Bitmap オブジェクトを破棄するのが最善の解決策であることはわかっていますが、同じコードを実行したときにこれら 2 つのマシンの動作が異なるのはなぜでしょうか?

4

2 に答える 2

1

Windows では、プログラムの動作に不機嫌になり、それ以上の割り当てを拒否する前に、10,000 個のハンドルをリークすることが許可されています。それまでに、ビットマップ内のピクセル データ用に大量の仮想メモリ スペースを消費しています。アンマネージ メモリに格納されているため、ガベージ コレクターはそれを認識しません。Dispose() を呼び出すか、ガベージ コレクターがファイナライザーを実行して処理しない限り、解放されない VM スペース。

通常、GC はジョブを完了しません。Bitmap クラスは非常に小さなオブジェクトであり、それ自体で GC をトリガーするのに十分な大きさではありません。GC をトリガーするには、約 60,000 個を割り当てる必要があります。ビットマップが非常に小さく、次に処理しない限り、最初に VM スペースが不足します。Dispose() の呼び出しはオプションですが、ファイナライザーが時間内にジョブを完了できないため、ビットマップの場合はオプションではなくなります。

RAM の量はこれには何の役割も果たしません。.NET プログラムは常に、要求されたサイズに適合するのに十分な大きさの VM アドレス空間の穴を見つけることができないことに爆撃します。ビットマップの問題もあり、大きな穴が必要になる傾向があります。厄介なベース アドレスにロードされる DLL が必要なだけで、すばらしい大きな穴が 2 つに切り分けられます。それ以外の場合は、プログラムのターゲット プラットフォームを AnyCPU に設定するだけで簡単に解決できる問題です。テスト プログラムには、そのための構成値があります。そのWin7マシンで動作します。しかしもちろん、それは Dispose() 呼び出しをスキップする正当な理由ではありません。

于 2013-09-30T13:47:10.867 に答える
1

これを読んでください: http://blogs.technet.com/b/markrussinovich/archive/2010/02/24/3315174.aspx

GDI ヒープに関するさまざまなバージョンの Windows 間の相違点の表があります。簡単な答え: XP = 3Mb 制限、Win7R2x64 = 20Mb 制限。空き RAM は問題ではありません。これらはハード リミットです。

于 2013-09-30T13:40:08.807 に答える