それは私には決して起こらなかったし、私は何年もプログラミングをしてきました。
malloc
が実際に機能しない非自明なプログラムの例を教えてもらえますか?
メモリの枯渇について話しているわけではありません:ユーザーが指定したバウンドサイズでメモリブロックを1つだけ割り当てている場合、たとえば整数を使用すると、malloc
が失敗する単純なケースを探しています。
はい。
システムが提供できる以上のメモリをmalloc
してみてください(アドレス空間を使い果たすか、仮想メモリのどちらか小さい方)。
malloc(SIZE_MAX)
おそらくそれを行います。そうでない場合は、なくなるまで数回繰り返します。
組み込みシステムでいくつかの作業を行う必要があります。頻繁にNULLが返されます:-)
現代の大規模なアドレス空間およびバッキングストアシステムでメモリ不足になることははるかに困難ですが、GISやインメモリデータベースなどの大量のデータを処理するアプリケーションや、バグのあるコードはメモリリークを引き起こします。
しかし、あなたがそれを経験したことがないかどうかは本当に重要ではありません-標準はそれが起こる可能性があるので、あなたはそれに応えるべきだと言います。私も過去数十年で車に見舞われたことはありませんが、だからと言って最初を見ずに道路を歩き回るわけではありません。
そして、あなたの編集を再:
私はメモリの枯渇について話していません...
definitionのメモリ枯渇は、malloc
が目的のスペースを提供しないことです。使用可能なすべてのメモリの割り当てによるものか、ヒープの断片化によるものかは関係ありません。つまり、メモリアリーナ内のすべての空きブロックの集合が高くても、連続ブロックを取得できません。 :
void *malloc (size_t sz) { return NULL; }
C標準は、失敗のmodesを区別せず、成功するか失敗するかだけを区別します。
OSで現在許可されているよりも多くのメモリを動的に割り当てる必要がある、cで記述されたプログラム。
楽しみのために、ubuntuタイプを使用している場合
ulimit -v 5000
1つのプロセスに使用可能なメモリの量を適切な量に制限しているため、実行するプログラムはおそらく(mallocの失敗により)クラッシュします。
メモリがすでに完全に予約されている(または重い断片化されている)場合を除き、malloc()
がNULL
- pointerを返す唯一の方法は、サイズ0のスペースを要求することです。
_char *foo = malloc(0);
_
C99標準、§7.20.3、サブセクション1から引用:
要求されたスペースのサイズがゼロの場合、動作は実装定義されます。nullポインタが返されるか、サイズがゼロ以外の値であるかのように動作します。ただし、返されたポインタはオブジェクトへのアクセスに使用されません。
言い換えると、malloc(0)
はNULL
- pointerまたはゼロが割り当てられたバイトへの有効なポインターを返す場合があります。
malloc
のマニュアルページを確認してください。
成功した場合、関数によって割り当てられたメモリブロックへのポインタ。
。
関数が要求されたメモリブロックの割り当てに失敗した場合、nullポインターが返されます。
多かれ少なかれ標準的なシステムで、標準的な1パラメーターmallocを使用すると、3つの可能性のある障害モードがあります(考えられることです):
1)要求された割り当てのサイズは許可されていません。たとえば、一部のシステムでは、使用可能なストレージが増えても、16Mを超える割り当てが許可されない場合があります。
2)要求されたサイズの連続した空き領域は、デフォルトの境界で、ヒープ内に配置できません。ヒープはまだたくさんありますが、1つのピースでは十分ではありません。
3)割り当てられたヒープの合計が、「人工」の制限を超えました。たとえば、単一の結合ヒープ内の「システム」に200Mの空き領域があり、利用可能な場合でも、ユーザーは100Mを超える割り当てを禁止される場合があります。
(もちろん、いくつかのシステムはヒープが成長するにつれてアドレス空間の不連続ブロックをヒープに割り当て、ブロックの合計に「ヒープサイズ制限」を設定するため、2と3の組み合わせを取得できます。)
一部の環境では、アライメントやプールIDなどの独自のツイストを追加できる追加のmallocパラメーターがサポートされていることに注意してください。
プラットフォームを選択しますが、おそらく組み込みが簡単です。 malloc
(またはnew
)トンRAM(またはリークRAMアルゴリズム)。ブームmalloc
は、「悪い」ことが起こっているときに、NULL
を返します。
編集への応答。はい、もう一度。時間の経過に伴うメモリの断片化により、int
の単一の割り当てでも失敗する可能性があります。また、malloc
はint
に4バイトを割り当てるだけでなく、必要なスペースを確保できることに注意してください。独自のブックキーピング機能があり、32〜64バイトの最小値を取得することがよくあります。
あなたが例を求めたので、ここに(最終的に)malloc
return NULL
を見るプログラムがあります:
_perror();void*malloc();main(){for(;;)if(!malloc(999)){perror(0);return 0;}}
_
何?意図的に難読化されたコードが嫌いですか? ;)(数分間実行され、マシン上でクラッシュしない場合は、それを強制終了し、_999
_をより大きな数に変更して再試行してください。)
編集:数字がどれだけ大きくても機能しない場合は、システムが「ここにメモリがあります!」と言っているということです。ただし、使用しようとしない限り、割り当てられません。その場合:
_perror();char*p;void*malloc();main(){for(;;){p=malloc(999);if(p)*p=0;else{perror(0);return 0;}}
_
トリックを行う必要があります。 GCCエクステンションを使用できる場合は、char*p;void*malloc();
をvoid*p,*malloc();
に変更することでさらに小さくできると思いますが、本当にゴルフをしたい場合は、Code Golf SEを使用します。
はい。カーネル/システムライブラリがメモリを割り当てられないことが確実な場合、MallocはNULLを返します。
最近のマシンで通常これが表示されない理由は、Mallocが実際にメモリを割り当てず、プログラムに「仮想アドレス空間」を予約して、書き込みを要求するためです。最新のLinuxなどのカーネルは、実際にオーバーコミットします。つまり、システムのアドレス空間にすべて収まる限り、システムが実際に提供できる以上のメモリ(スワップ+ RAM)を割り当てることができます(通常64ビットプラットフォームでは48ビット、IIRC) 。したがって、これらのシステムでは、おそらくNULLポインターの戻りをトリガーする前にOOMキラーをトリガーします。良い例は、32MBマシンで512MB RAMです。利用可能なすべてのRAM +スワップ。
(Linuxではコンパイル時にオーバーコミットを無効にできるため、特定のLinuxカーネルがオーバーコミットするかどうかはビルドオプションに依存します。ただし、標準のデスクトップディストリビューションカーネルはそれを行います。)