質問する前に、ちょっとした免責事項を述べておきます。はい、仮想メモリ、物理メモリ、およびワーキング セットの違いを認識しています。以下のすべての数字は、仮想メモリを指します。
状況は次のとおりです。x86 C++ ライブラリをインポートする 32 ビット C# アプリがあります (多くのネイティブ依存関係があるため、x64 への移行は現時点ではオプションではありません)。アプリはアンマネージ コンポーネントを介して大規模なデータセットを読み込み、それを表示 (レポート) しようとします。
ただし、データセットが特に大きい場合、以下のコードのように、項目をリストに追加すると OutOfMemory 例外がスローされます。
ここで驚きはありません。ただし、驚くべきことは、アプリケーションがまだ約 280MB の空き VM を持っているという事実です。
純粋なアンマネージ アプリ (C++) をデバッグする場合は、そうではありませんでした。bad_alloc は、空き VM が残っていない場合、または十分なサイズの空きアドレス空間チャンクがない場合にのみ達成できました。
したがって、質問 - これの理由は何ですか? この問題に対処する方法は理解しています。管理されていないコンポーネントは実際に大量のメモリを消費し、多くの断片化を作成します。しかし、OutOfMemoryException が非常に早く表示される理由は何ですか?
問題のコードは次のようになります。
List<Cell> r = new List<Cell>(cols);
for (int j = 0; j < cols; j++)
{
r.Add(new CustomCell()); // The exception is thrown on this line
}
例外が発生した時点で、リストには 85 個の項目があり、その容量は 200 程度 (コンストラクターで示される列の数) でした。そのため、例外は CustomCell の割り当てで発生した可能性が最も高いです。CustomCell オブジェクトには多くのフィールドがありますが、確かに合計で 1KB 未満です。280MB の空きメモリは 64KB から 14MB のチャンクに配置されているため、割り当てるには十分なスペースがあるはずです。