windows - 配列 - ビット フィールド 64bit




64ビットの大規模なmallocs (6)

しかし、なぜmallocが失敗するのでしょうか? 私は他の理由を考えることができません

前に暗黙に述べたように、メモリの断片化

malloc()が特に64ビットで失敗する理由は何ですか?

私の具体的な問題は、64ビットシステム上で巨大な10GBのRAMチャンクをmallocしようとしていることです。 マシンは12GBのRAMと32GBのスワップを備えています。 はい、mallocは極端ですが、なぜ問題になるのでしょうか? これは、インテルとMSFTの両方のコンパイラを備えたWindows XP64にあります。 mallocは成功することがありますが、時にはそうではありません。約50%です。 8GBのmallocは常に動作しますが、20GBのmallocは常に失敗します。 mallocが失敗した場合、プロセスをやめて新たなプロセスを再開しない限り、繰り返し要求は機能しません(成功した場合は50%のショットを取得します)。 他の大きなアプリは動いていません。 新しくリブートした直後でも起こります。

32ビット(または31ビット)のアドレス空間を使い切ってしまった場合、要求に割り当てられるほどのアドレス範囲がないため、32ビットでmallocが失敗すると思います。

物理RAM ハードドライブのスワップ領域を使い切ってしまった場合、mallocが失敗することも想像できます。 これは私には当てはまりません。

しかし、なぜmallocが失敗するのでしょうか? 私は他の理由も考えられません。

とにかくメモリマップされたファイルで置き換えられると思われる私の具体例よりも、一般的なmalloc質問にもっと興味があります。 失敗したmalloc()は、あなたのツールを理解し、基本に驚かないことを望む他のものよりもパズルのほうがはるかです。


mallocは連続したメモリ範囲を割り当てようとしますが、これは最初はスワップメモリ​​がどのように機能するかによって(少なくとも私が覚えている限り)実際のメモリになります。 あなたのOSが時には連続した10GBのブロックを見つけられず、RAMに同時に実際のメモリを必要とするすべてのプロセスを同時に残すことができます(その時点であなたのmallocは失敗します)。

あなたは実際に10GBの連続したメモリを必要としますか?あるいは、いくつかの小さなブロックの周りにストレージクラス/構造体をラップして、代わりにチャンクであなたのメモリを使用することができますか? これにより、連続した巨大な要件が緩和され、プログラムで使用されていないチャンクにスワップファイルを使用できるようになります。


ここでは、ヒープの最大要求サイズがリンクされたCRTライブラリによって定義されていることを公式に示しています(整数オーバーフローが0になっているため、NULLを返さなかった理由はありません)(_HEAP_MAXREQ)。

http://msdn.microsoft.com/en-us/library/6ewkz86d.aspx

私の答えは大きなウィンドウの割り当てについてはhereをチェックしてください。私は、Vista / 2008メモリモデルの進歩に関するMS論文への参照を含みます。

要するに、在庫CRTはネイティブの64ビットプロセスであっても、4GB以上のヒープサイズをサポートしていません。 VirtualAlloc *やCreateFileMappingなどのアナログを使用する必要があります。

ああ、私はあなたの大規模な割り当てが実際に成功していると主張していることに気付きました。これは実際には間違っています。あなたはmalloc(0x200000000)を誤解しています。 (これは16進数で8GBです)、何が起こっているのは、テストハーネスのキャストや他の効果のために0バイトの割り当てを要求していることです.0xfffff000バイトのヒープがコミットされているよりも大きなものはほとんど見かけません。単純に整数のオーバーフローがキャストダウンしているのを見ているだけです。

ワイプへの言葉、またはヒープ・サンティを保存するためのヒント*

MALLOC(または他の動的要求)を使用してメモリを割り当てるだけの方法

void *foo = malloc(SIZE);

ダイナミックメモリ要求の価値は、要求の "()" PARENの中で決して(必ずしも厳しくすることはできません)計算されなければなりません

mytype *foo = (mytype *) malloc(sizeof(mytype) * 2);

危険は、 整数のオーバーフローが発生することです。

呼び出し時に算術演算を実行するのは常にコーディング・エラーです。要求を評価するステートメントの前に、要求されるデータの合計を常に計算しなければなりません

なぜそれはとても悪いですか? これが間違いであることはわかっています。動的リソースに対する要求があるため、将来このリソースを使用するポイントが必要です。

私たちが要求したものを使用するには、それがどれだけ大きいかを知る必要があります。 (例えば、配列数、型サイズなど)。

これは、資源要求の中で算術が全く見えなくても、そのデータを適切に使うためには、そのコードを再度複製しなければならないということです。


ここでは推測しますが、mallocは連続したメモリを割り当てます。ヒープ上に十分大きな連続セクションがないかもしれません。 私が試してみたいことがいくつかあります。

20GBのmallocが失敗すると、5GBのmallocが4つ成功しますか? そうであれば、それは連続したスペースの問題です。

あなたは、ヒープサイズの合計、または最大のヒープブロックサイズを制限するものについて、コンパイラスイッチをチェックしましたか?

あなたは、必要なサイズの静的変数を宣言するプログラムを書こうとしましたか? これがうまくいくならば、そのスペースに大きなmallocを使って独自のヒープを実装することができます。



問題は、64ビットアプリケーションをコンパイルするときにVisual StudioがWIN64を定義していないことです。通常は64ビットアプリケーションでは間違ってWIN32を保持します。 これにより、 _HEAP_MAXREQが定義されているときに実行時に32ビット値が使用されるため、すべての大きなmalloc()は失敗します。 あなたのプロジェクト(プロジェクトのプロパティ、前処理された定義の下で)をWIN64に変更した場合、非常に大きなmalloc()は何の問題もないはずです。







virtual-memory