割り当てを確実に成功させるために、do...while ブロックに malloc を入れることはできますか?
お気に入り:
#define STR_SIZE 1024 * 1024
char *str;
do
str = (char *) malloc(STR_SIZE);
while ( !str );
malloc
失敗することはめったになく、リソースが使い果たされると失敗し、これらはすぐには利用できないため、おそらく機能しません。
より多くのリソースを取得できる唯一の一般的なケースmalloc
は、他の大きなプロセスが大量のメモリを解放する場合です。それを気にする場合は、ループに少なくとも a を追加し、本当に失敗して常に返すsleep
ケースを処理する準備をしてください。malloc
NULL
より良い方法は、結果をテストmalloc
し、失敗とエラー メッセージで終了することです。
char* str = malloc(STR_SIZE);
if (!str) {
perror("malloc failed for str");
exit (EXIT_FAILURE);
}
また、すべてのプログラムは、失敗した場合に対処する必要がありmalloc
ます (通常はエラー メッセージで終了します)。
多くのプログラムは、失敗したときに-s または-sxmalloc
の関数を呼び出し、成功したときに割り当てられたゾーンを返しますexit
abort
malloc
malloc の失敗 (つまり、実行を継続できるようにするための処理) を適切に処理するのは非常に困難です。一部のプログラムは、たとえばfree
、他のグローバル データなどである可能性があります。実際、これは特殊なガベージ コレクションメカニズムを実装することになります。一部のサーバーは現在のリクエストを失敗させる可能性があります (現在失敗したリクエストで使用されているすべてのリソースを解放し、細心の注意を払ってこれを行う必要があります)。
そしてmalloc
、利用可能なリソースよりも多くのリソースが必要な場合、本当に失敗する可能性があります. したがって、そのケースを処理する必要があります。
ところで、Boehm の保守的なガベージ コレクターを使用することを検討して、GC_malloc
代わりに使用し、その失敗や-ingmalloc
を気にしないでください。free
(Boehm の GC は、メモリが不足するとプログラムを中止すると思います)。
他の回答が指摘しているように、あなたのコードには欠陥があります。ただし、背後にある考え方は完全に不合理というわけではありません。
Basile's answermalloc
で概説されているように、失敗を処理するための古典的なアプローチは、プログラムを終了させることです。の戻り値をチェックするコードは、多くの場合、 などと呼ばれる一般的なラッパー関数に配置され、 の代わりに一貫して使用されます。これは簡単に実装して推論できますが、欠陥がないわけではありません。これは通常、Unix シェルから呼び出されるような短命のコマンド ライン プログラムでは非常に理にかなっていますが、プログラムがメモリ不足になってもすぐに停止することが不適切な対話型プログラムでは失敗します。 . ライブラリを使用するプログラムは、単一の割り当てが失敗したという理由だけでプロセスを終了させたくない場合があるため、ライブラリコードにも適していません。malloc
xmalloc
malloc
メモリの問題がプログラムの動作に起因しない可能性が高い場合、割り当てを再試行することは理にかなっています。たとえば、マルチプロセスの HTTP サーバーは、単一のメモリ割り当てが失敗した直後にリクエストを拒否してプロセスを終了したくない場合があります。ただし、適切な実装は次のとおりです。1) ビジー ループを回避し、システムに回復の機会を与えるために、リクエスト間でスリープするように注意し、2) プロセスがプロセスである場合に備えて、プロセスが何度か繰り返された後に終了することを確認します。それ自体が割り当ての失敗を引き起こしています。例えば:
void *safe_malloc(size_t howmuch)
{
int i = 0;
while (i++ < 10) {
void *ptr = malloc(howmuch);
if (ptr)
return ptr;
sleep(i);
}
perror("malloc");
exit(EXIT_FAILURE);
}
このアプローチは、現在は廃止されたphttpd Web サーバーなどのサーバーで使用されています。
対話型アプリケーションでの失敗に対する別のアプローチmalloc
は、Emacs で使用されるものです。一定量のメモリが起動時に割り当てられ、後で使用できるように保存されます。メモリ割り当てが失敗すると、救済メモリが解放され、Lisp レベルの例外が発生して、現在の操作が破棄されます。ユーザーに状況を説明する警告メッセージが表示されます。解放されたメモリにより、プログラムは、Emacs がダウンする前にユーザーが作業を保存するのに十分な時間、作業を続けることができます。
確かに、しかしSTR_SIZE
不合理な場合、これはコードを永久にロックします。
メモリが非常に断片化されている場合、まれに Malloc が失敗することもあります。この場合、コードは機能します。
まれにmallocが失敗する可能性がありますが、構文的には正しいですが、論理的に正しいかどうかはわかりません。機能する場合はコーディングを試みます。