C++標準に従って、新しいメモリの割り当てに失敗した場合、std :: bad_alloc例外をスローすることになっています。しかし、VC6(またはCRT実装?)などの一部のコンパイラはこれに準拠していないと聞いています。これは本当ですか ?新しいステートメントのたびにNULLをチェックすると、コードが非常に見苦しくなってしまうので、これを求めています。
この点に関して、VC6はデフォルトでは非準拠でした。 VC6のnew
は0
(またはNULL
)を返しました。
この問題に関するMicrosoftのKB記事は、カスタムnew
ハンドラーを使用した推奨される回避策と一緒です。
VC6の動作用に作成された古いコードがある場合は、nothrownew.obj
という名前のオブジェクトファイルにリンクすることにより、新しいMSVCコンパイラ(7.0以降など)で同じ動作を取得できます。 7.0および7.1コンパイラ(VS2002およびVS2003)には、デフォルトで非スローまたはスローのnew
を決定する かなり複雑なルールセット があります。
MS clean this up 8.0(VS2005)— nothrownew.obj
に特にリンクしない限り、常にデフォルトのthrowing newになります。
0
パラメーターを使用してstd::bad_alloc
をスローする代わりに、new
がstd::nothrow
を返すように指定できることに注意してください。
SomeType *p = new(std::nothrow) SomeType;
これはVC6で機能するように見えるため、すべてのコンパイラで同じように機能するようにコードを多少機械的に修正し、既存のエラー処理をやり直す必要がないようにすることができます。
割り当ての試行後にNULLをチェックすることは無益であるという(やや物議を醸す)意見を追加したいと思います。プログラムがそのような状況に陥った場合、すぐに終了する以上のことはできないでしょう。後続の割り当て試行も失敗する可能性が非常に高くなります。
NULLをチェックしないと、後続のコードはNULLポインターの逆参照を試みます。NULLポインターは、比較的一意の(簡単にデバッグ可能な)終了条件でプログラムを高速に終了する傾向があります。
NULLのチェックについて話をしようとはしていませんが、それは確かに良心的なプログラミングです。ただし、回復情報を(メモリを追加せずに)保存したり、重要度の低いメモリを解放したりできる非常に特殊な場合を除いて、それほど多くは得られません。しかし、これらのケースはほとんどの人にとって比較的まれです。
これを考えると、私はコンパイラーが個人的にbad_allocを投げると信じていました-少なくともほとんどの場合。
C++仕様に基づいて、paramsなしで単なるnewを使用すると、常にstd :: bad_allocがスローされますが、もちろん、いくつかの非準拠コンパイラーが存在する可能性があります。
ただし、C++に準拠していないコンパイラに準拠するコードは作成しません。この点でVC6はそれらの1つです。
ただし、削除した後は常にポインターをNULLに設定することをお勧めします。そのため、NULLをチェックする必要があります。
つまり、コードをクリーンアップするためのいくつかのオプションがあります。
オプション1:独自の新しいハンドラーを設定する
コードをクリーンアップする安全な方法は、最初に set_new_handler を呼び出すことです。
その後、ハンドラーでNULLをチェックし、NULLが返された場合はそこにstd :: bad_allocをスローできます。
例外を好む場合、これが最善の策です。 NULLをより適切に返したい場合は、新しいハンドラー内でcatchを実行することでもできます。
オプション2:オーバーロードされたnewを使用する
C++標準ヘッダーファイルは、空のstruct nothrowを定義します。この構造体のオブジェクトをnew内で使用して、常にNULLを返すオーバーロードバージョンを取得できます。
void* operator new (size_t size, const std::nothrow_t &);
void* operator new[] (void *v, const std::nothrow_t &nt);
あなたのコードで:
char *p = new(std::nothrow) char[1024];
ここに さらに読むための良い参考文献