誰かがメモリ不足の例外をキャッチする方法を教えてもらえますか?
例えば.
try
{
while(true)
{
int i = new int;
}
}
catch( ? <--- what should be put here?)
{
//exception handling
}
そしてこれも
queue<int> q;
try
{
while(true)
{
q.Push(10);
}
}
catch( ? <---- what should be put here?)
{
//error handling
}
キャッチ std::bad_alloc
。
エラーを処理するための戦略も必要になります。実行したいことの多くはメモリを必要とするためです(シャットダウンする前にユーザーにエラーを表示するだけの場合でも)。 1つの戦略は、起動時にメモリブロックを割り当て、それを例外ハンドラbeforeでdelete
割り当てて、より多くのメモリを使用しようとするため、使用可能なものがあること。
他の人が指摘したように、キャッチしたいのは_std::bad_alloc
_です。 catch(...)
またはcatch(exception& ex)
を使用して、例外をキャッチすることもできます。後者の場合、例外データを読み取り、例外ハンドラーで使用できます。
マークランサムは、プログラムがこれ以上メモリを割り当てることができない場合、エラーメッセージの印刷でさえ失敗する可能性があることをすでに指摘していました。次のプログラムを検討してください。
_#include <iostream>
using namespace std;
int main() {
unsigned long long i = 0;
try {
while(true) {
// Leaks memory on each iteration as there is no matching delete
int* a = new int;
i++;
}
} catch(bad_alloc& ex) {
cerr << sizeof(int) * i << " bytes: Out of memory!";
cin.get();
exit(1);
}
return 0; // Unreachable
}
_
(64ビットマシンでシステムがメモリ不足になるのを防ぐため、プログラムを32ビットとしてコンパイルすることを強くお勧めします。32ビットプログラムは4 GB以上、またはデフォルトで2 GB以上のメモリを割り当てることはできませんWindowsの場合)
最初の_bad_alloc
_が無限のwhile
ループでスローされると、制御はcatch
ブロックに渡されますが、プログラムは未処理の例外で失敗します。どうして?別の_bad_alloc
_がスローされます例外ハンドラー内cerr
に出力しようとしています。これは、デバッガーを使用して確認できます。catch(bad_alloc& ex)
行にブレークポイントを設定し、デバッガーでプログラムを実行し、ブレークポイントに到達したら各ステートメントをステップ実行します。 cerr
ステートメントで_bad_alloc
_例外がスローされます。
そのため、メモリ不足のシナリオを適切に処理するには、終了する前にエラーメッセージを出力できるようにメモリを確保する必要があります。それ以外の場合、プログラムは、エラーメッセージを出力しようとしているときに、未処理の例外でクラッシュするだけです。そのためには、Mark Ransomが提案したように、例外ハンドラーで割り当て解除されたメモリブロックを割り当てることができます。
_// Reserve 16K of memory that can be deleted just in case we run out of memory
char* _emergencyMemory = new char[16384];
// ...
try {
// ...
} catch(bad_alloc& ex) {
// Delete the reserved memory so we can print an error message before exiting
delete[] _emergencyMemory;
cerr << sizeof(int) * i << " bytes: Out of memory!";
cin.get();
exit(1);
}
//...
_
catch (std::bad_alloc& ba){
cerr << "bad_alloc caught: " << ba.what() << endl;
}
メモとして、bdonlanのコメントを読んでください。 cerr
の呼び出しは非常に失敗する可能性があります。 Mark Ransomの答えでの提案は、この問題を緩和するための優れた戦略です。
catch
型のオブジェクトstd::bad_alloc
。
または、nothrow
のnew
バージョンを次のように使用することもできます。
int *pi = new (nothrow) int[N];
if(pi == NULL)
{
std::cout << "Could not allocate memory" << std::endl;
}
これを使用すると、new
が失敗しても例外はスローされません。代わりに、単に先に進む前に確認するNULL
を返すだけです。