2009-05-26 11 views
7

大きなリストを構築してメモリに保持する必要がありますが、構築中にOutOfMemoryExceptionがスローされます。リソースモニターによれば、私はまだ1GBのメモリを利用できます。私はthis KB articleがこの問題に対処しているのを見つけましたが、フレームワーク1.1 SP1(3.5 sp1を使用しています)で修正されているはずです。OutOfMemoryExceptionはメモリがまだ利用可能な間にスローされます

舞台裏で何が起きているのか誰かが気をつけてもらえますか? .netフレームワークは、1つのプロセス(32ビットシステム上)で使用できるメモリの量を制限していますか?もしそうなら、私は理由を知ることができますが、アプリケーションが1.6GBしか使用しておらず、まだシステムに〜1GB残っているということは意味がありません。

編集 - ここに尋ねた人のためには、いくつかのより詳細な情報は以下のとおりです。

私がリストを持っている(ええ、私は何か他のものを使用することができますが、私はちょうど今試作しています。)、私が発生Guid.NewGuid()。ToString()を実行してランダムな文字列を作成し、それをリストにスローします。私がしようとしているのは、私がそれに合うような数のアイテムを含むリストを生成し、特定のものを探すさまざまな方法をテストすることです。私の最初の推測では、いくつかの断片化が進行中ですが、私は以下のコードを除いてすべてを落としました。私はこの小さなスニペットが多くの断片化を作り出すとは思わないが、おそらく間違っている。

 List<string> blah = new List<string>(); 

     for (int i = 0; i < 50000000; i++) 
     { 
      blah.Add(Guid.NewGuid().ToString()); 
     } 
+0

あなたはOutOfMemoryExceptionを打つ場所のコードスニペットを提供できますか? –

+0

どのデータ構造を使用していますか?リスト? – RichardOD

答えて

9

のためのこれらのリンクを参照してください。メモリを断片化して、リストに項目を追加しようとすると、サイズを変更する必要があります。使用可能なメモリのブロックは保持できません。

これはOutOfMemoryExceptionにもつながります。

例外が発生した場合、リストの大きさ、言い換えれば、正確に、または大まかに、そこにいくつの文字列がありますか?

あなたはどのようにリストに値を設定していますか?あなたが追加するアイテムの数を事前に知っていますか?もしそうなら、リストを作成するときに容量を指定しますか?

わからない場合は、それを把握することができますか?その容量を指定できますか?

+0

リストのサイズを指定すると、ありがとう! – Joe

0

私はこのバグの詳細を本当に知っていませんが、何年も前にこれに似ています。重要なことは、アプリケーションがバインドされているGDIハンドルの量に厳しい制限があることがわかったということです。 9,999のようなもの。この制限に達すると、どれくらいのメモリが空いていてもアプリケーションはメモリ不足の例外でクラッシュします。

あなたは何か似たようなことをしているかもしれませんが、文字列を扱っていると言われているので、ヒープを断片化して容量を超えていると思います。文字列が十分大きければ、おそらくラージオブジェクトヒープ上にあります。 LOHの実装は、フレームワークの初期バージョンでは非常に貧弱だったと思います。メモリが正しく機能していれば、オブジェクトは適切に割り当て解除されず、LOHのみのスペースが使い尽くされやすくなりました。

は、問題は、あなたが「利用可能」メモリを持っていますが、あなたがきた可能性が高くないということはおそらくないが、いくつかのより多くの情報

http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/ http://msdn.microsoft.com/en-us/magazine/cc534993.aspx http://blogs.msdn.com/maoni/archive/2006/04/18/large-object-heap.aspx http://social.msdn.microsoft.com/Forums/en-US/clr/thread/08e6bd5f-613e-41ae-9ab1-b05c7ff2710f

9

Win32には、プロセスあたり2GBのメモリ制限があります。実際には4GBですが、OS起動オプションが/3GBに設定されていない限り、2GBはカーネルモード用に予約されています。

+1

彼は1.6GBしか見せていませんが、私は彼が断片化するためにその一部を失っていると思います。 –

+1

Mark Russinovichのブログには、Windowsの物理メモリの限界に関する詳細な情報が含まれています。http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx – RichardOD

+1

P&P規定のアーキテクチャには、 http://msdn.microsoft.com/en-us/library/ms998583.aspx#scalenetchapt17_topic9 – RichardOD

2

リスト<のデフォルトのコンストラクタT >は、空の配列で内部ストレージとして開始されます。 Add(Tアイテム)を呼び出すと、配列のサイズ変更が必要かどうかがチェックされ、の容量プロパティ(EnsureCapacityメソッド経由)になります。 Capacityプロパティは、それを設定している場合...

  1. は、新しいサイズ(ダブルオリジナル!)新しいものに古いものから
  2. 要素をコピーして新しい配列を作成します。
  3. 内部参照を新しいものに変更します。

したがって、nの容量を仮定すると、リサイズ中に合計メモリ使用量が3nになります。

あなたのリストは、失敗したときにいくつのアイテムを含んでいますか? 追加するアイテムの数がわかっている場合は、容量を受け入れるコンストラクタを使用してみてください。これにより、実行する必要のあるリサイズが回避されます(巨大なメモリブロックが必要な場合はOutOfMemoryExceptionが直接スローされる可能性があります)。

1

フラグメンテーション、LargeAddressAware、またはgcAllowVeryLargeObjectsを忘れてしまいました...この正確な状況に関する私の問題は、コンソールプロジェクトの[プロパティ]ページの[ビルド]で[32ビット優先]チェックボックスをオフにして解決しました。これはデフォルトで設定されています...なぜですか?

+0

それは私のためにも働く –

関連する問題