web-dev-qa-db-ja.com

新しい演算子でメモリ割り当ての失敗を確認するにはどうすればよいですか?

最近、プロジェクトの言語をCからC++を使用するように切り替えました。Cでは、mallocを使用し、その後、mallocが成功したかどうかを確認しますが、C++では、 'new'を使用してメモリを割り当てます。通常、メモリ割り当ての失敗を確認します。

私のグーグル検索から、私は次のようにノスローを見た.

char *buf = new (nothrow)char[10];

以下も見ました。

try{} catch(bad_alloc&) {}

しかし、以下についてはどうですか? chromeライブラリルーチンの一部を使用してスマートポインターを使用しています。

たとえば、次のようなコードがあります。

scoped_array<char> buf(new char[MAX_BUF]);

スマートポインターを使用するのは素晴らしいことですが、メモリの割り当てが成功したかどうかを確認する方法がわかりません。 nothrowまたはtry/catchで2つの別々のステートメントに分割する必要がありますか?通常、C++でこれらのチェックをどのように行いますか?

どんなアドバイスもいただければ幸いです。

27
istudy0

さて、bad_allocをスローするnewを呼び出すので、それをキャッチする必要があります。

try
{
    scoped_array<char> buf(new char[MAX_BUF]);
    ...
}
catch(std::bad_alloc&) 
{
    ...
}

または

scoped_array<char> buf(new(nothrow) char[MAX_BUF]);
if(!buf)
{
   //allocation failed
}

私の答えは、スマートポインターが例外を伝達するということです。したがって、通常のスロースローでメモリを割り当てる場合は、例外をキャッチする必要があります。 nothrow newで割り当てる場合は、nullptrを確認する必要があります。いずれにせよ、スマートポインターはこのロジックに何も追加しません

20
Armen Tsirunyan

私はそれを言うのが嫌いですが、IMO、あなたは間違った方向に進んでいます(そして、残念ながら、あなたが得た他の答えもあなたを本当に正しい方向に向けていませんでした)。

newのさまざまな種類のスマートポインターやノーマルバリアントとnothrowバリアントのどちらかを選択するのではなく、おそらく実行していることから少なくとも2つ以上ステップを戻す必要があります。手動で管理する動的データ構造をコレクションに置き換えます。これはalwaysが正しい選択ではないかもしれませんが、少なくとも私の経験では、lotより多くの場合、正しい方法です。標準ライブラリには多くの可能性(ベクトル、デキュー、リスト、セットなど)があり、newおよび会社と直接やり取りするのではなく、そのうちの1つを使用できる可能性はかなり高いです。

デフォルトでは、これらはnewの通常の(スローする)バリアントを使用するアロケーターを使用します。したがって、通常は、ほとんどのコードをかなり高いレベルでtryブロックに配置し、メモリ不足を処理するcatch句を設定します。

メモリの割り当てを直接処理する必要がある場合は、通常のアルゴリズムとイテレータで動作するように、ライブラリ内の標準コンテナと同様のインターフェースを提供する可能性がかなり高いでしょう。既存のコンテナを使用した最初の経験は、この時点に到達した時点で十分に報われます。

16
Jerry Coffin

C++には、newがメモリを割り当てる方法が2つあり、それぞれに異なるエラーチェックが必要です。

標準のnew演算子は、失敗するとstd::bad_alloc例外をスローし、これは通常の例外と同様に処理できます

try {
  char* c = new char[100];
} catch (std::bad_alloc&) {
  // Handle error
}

または、代わりにnothrownewバージョンは、失敗するとNULLを返すだけです。

char* c = new (std::nothrow) char[100];
if (!c) {
  // Handle error
}

割り当てが失敗したときにあなたが何を期待するかについて私は興味がありますか?オブジェクトを割り当てるために使用できるメモリがない場合、プロセスで実行できることはほとんどありません。

6
JaredPar

メモリ割り当ての失敗を確認する必要があります。

どちらか

scoped_array<char> buf;

try {
  buf.reset( new char[MAX_BUF] );
} catch( std::bad_alloc& ) {
  // Handle the failure
}

または

scoped_array<char> buf( new(std::nothrow)char[MAX_BUF] );

if( buf.get() == NULL ) {
   // Handle the failure
}
1
Praetorian