割り当てが失敗した場合malloc
、もう一度やり直すべきですか?
このようなもので:
char* mystrdup(const char *s)
{
char *ab = NULL;
while(ab == NULL) {
ab=(char*)malloc(strlen(s)+1);
}
strcpy(ab, s);
return ab;
}
while ループはメモリ割り当ての確認に有効ですか?
一般に、最新のmalloc()
実装はNULL
絶対的な最後の手段としてのみ返され、再試行してもまったく役に立ちません。メモリを解放してから再試行するだけで解決します。アプリケーションが消費可能なリソースを保持している場合は、これがそれらを解放してから、別のショットを実行するときです。
一部の環境では、雨の日の資金として少量のメモリを割り当てると便利な方法があります。が返された場合は、その万一の資金を解放し、エラーを処理して正常に終了できるようにするために必要なリソースを割り当てることができますmalloc()
。これは、古い Macintosh Toolbox でプログラミングするときの一般的な方法でした。が返された場合、そのスペースを使用してダイアログを作成し、終了する前に問題を報告できます。NULL
malloc()
NULL
シングルスレッドプログラムでは、試行の間にメモリを解放せずに「再試行」しても、実際には意味がありません。永遠にループします。
マルチスレッド プログラムでは、並列に実行されている別のスレッドが突然自身のメモリの一部を解放することを決定した場合、これは「機能する」可能性があります。このような場合のループは、古典的な「ビジー待機」ループを構成します。しかし、この場合でも、そのようなコードは複数の理由から実用的な価値がほとんどありません。
なぜ、いつこれが役立つのかについて議論することなく、少なくとも 64 ビット コードの Windows とデフォルトのページファイル設定では、ループ内での再割り当ての試行が機能する可能性があります。さらに、これにより、驚くほど多くの追加の仮想メモリを購入できます。ただし、これを無限ループで実行しないでください。代わりに、有限回数の再試行を使用してください。証拠として、1 Mb のメモリ リークをシミュレートする次のコードを試してください。できればデバッガーではなく、リリースビルドで実行する必要があります。
for (int i = 0; i < 10; i++)
{
size_t allocated = 0;
while (1)
{
void* p = malloc(1024 * 1024);
if (!p)
break;
allocated += 1;
}
//This prints only after malloc had failed.
std::cout << "Allocated: " << allocated << " Mb\n";
//Sleep(1000);
}
8 Gb の RAM とシステム管理のページファイルを備えた私のマシンでは、次の出力が得られます (x64 ターゲット用の VS2013 でビルドされ、Windows 7 Pro でテストされています)。
Allocated: 14075 Mb
Allocated: 16 Mb
Allocated: 2392 Mb
Allocated: 3 Mb
Allocated: 2791 Mb
Allocated: 16 Mb
Allocated: 3172 Mb
Allocated: 16 Mb
Allocated: 3651 Mb
Allocated: 15 Mb
このような動作の正確な理由はわかりませんが、ページファイルのサイズ変更がリクエストに追いつかないと、割り当てが失敗し始めるようです。私のマシンでは、このループの後、ページファイルが 8 GB から 20 GB に増加しました (プログラムが終了すると、8 GB に戻ります)。
いいえ、決して。malloc
NULL を返す場合はエラーを示しており、おそらく中止する必要があります。
これがあなたが望むことをすることは信じられないほどありそうにありません。メモリが不足している場合は、さらに取得するまでビジー ループを行うとがっかりする可能性があります。不要になったメモリを解放するか、エラーを返すことによって、リソースの枯渇に対処できるように、呼び出し元のプログラムに NULL を返す必要があります。
malloc() は、メモリを割り当てるために最善を尽くします。失敗した場合は、while ループでメモリの割り当てを再試行するのではなく (プログラムがそこで永遠に動かなくなる可能性があります)、可能であれば、他のプロセスまたはスレッドが保持しているメモリを解放してから再試行してください。
別の方法としては、スワップ ファイルまたはページング メモリをその場でコード自体から増やすことによって (ただし危険であり、好ましくありません)、手動でメモリを増やすこともできます。
このような問題を回避する最善の方法は、コード自体を記述しながらメモリ要件を計算または見積もることです。