2016-05-09 10 views
0

以下のコードは、if(m_buf)を使用して割り当てが正しく行われたかどうかを確認しています。 私は約2物事をさまよう有効な割り当てを確認する方法

char *m_buf; 

void String::_copy(const char* lpsz){ 
    if (lpsz != 0){ 
     int len = MyCString::strlen(lpsz); 
     m_buf = new char[len + 1]; 
     if (m_buf) 
      MyCString::strcpy(m_buf, lpsz); 
    } 
} 

(コードでは、いくつかのビデオチュートリアルからです)。
まず、本当に必要なコードですか?
第2に、new char[len+1]が正常に実行されたかどうかを実際に確認していますか?
charポインタの何かが真であるかどうかを調べるだけです。私はC文字列ポインタは文字列の最初のメモリアドレスを持っているが、それはすべての文字列メモリアドレスについて有効ではないはずです知っている?私は何を考えているのですが、演算子newは既に例外をスローしているコードを持っています。どうしてtry catchを使わないのですか?

オブジェクトを動的に割り当てて、割り当てが正常に行われたことを確認したいとします。あなたならどうしますか?私がオブジェクトを作るたびにこれを行うべきだと思いますか?

+1

'new'は失敗した場合に例外をスローします。したがって、このチェックは冗長です。 –

+0

"すべての文字列のメモリアドレスについて有効であってはいけません"は、IMOの基本的な理解の欠如を示しています。ポインタは単一の値で、メモリブロックの**開始アドレス**を示します。開始アドレスが有効である(つまり、プログラムのメモリの境界内にある)ことがわかると、ブロック内のすべてのアドレスをチェックする意味がありません。もちろん、これはすべて、ブロックが正しく割り当てられていることを前提としています。 –

+0

ところで:ちょうどあなたが学んでいるなら、それは大丈夫ですが、独自の文字列クラス/関数をロールするのは良い考えではないことに注意してください。 'std :: string'を使うと、メモリリークや' new'などを心配する必要はありません。 – szczurcio

答えて

0

失敗した場合はstd::bad_allocを投げるのでチェックは無意味です。

は、障害が発生した場合には、標準ライブラリの実装ではstd::get_new_handlerで返される関数ポインタを呼び出し、新しいハンドラが戻るか、std::bad_allocをスローし、その時点でNULLポインタを、となっていないまで割り当て試行を繰り返します。

new(std::nothrow) char[len + 1];のような新しく投げ入れられていないものを使用していない限り、チェックは意味があります。

は例外を伝播する代わりに、失敗した場合にnullポインタを返します。

http://en.cppreference.com/w/cpp/memory/new/operator_new

+0

一部のプログラムはC++で、例外は無効になっています。組み込みシステムプログラミングで。そのような文脈のために書くなら、チェックが必要です。 – BitTickler

+0

@BitTicklerあなたはそのような状況で行動が変わることを意味しますか? (私は彼らがこのような状況で新しい投球ではないと思った。)これはOPの質問に対する答えかもしれない。 – songyuanyao

+0

はい - 例外をサポートしているかどうかにかかわらず、コードを作成するかどうかをコンパイラに伝えることができます。このようなシナリオで作業するコードを記述したいかどうかは、決定するのはあなた次第です。 – BitTickler

1

非標準コンパイラを使用しない限り、これは無意味なチェックです。 newnullptrを返すことはできませんが、bad_alloc例外でのみ失敗することがあります。その場合はif -checkに達しません。

0

チェックは必要ありません(少なくともこの形式で)。

newが失敗すると、例外(std::bad_alloc)がスローされます。あなたのコードでは、関数を終了するので、ifは必要ありません。

の代わりにnullptrを返しますが、それを使用するには明示的に書き込む必要があります。

1

このコードは非常に古いと時代遅れの技術を示しています。初期のC++標準化プロセス(90年代初頭)では、いくつかのコンパイラ/ライブラリではエラーの際にNULLを返した演算子newしかサポートしていませんでした。例えば、ARM(標準化作業のための基本文書)は、オペレータnewが失敗して投げることを示唆していませんでした。、アップ固めnew演算子のための

要件 - と最初のC++標準に最終決定された - オペレータnewは、デフォルトでは、

void String::_copy(const char* lpsz 
{ 
    if (lpsz != 0) 
    { 
     int len = MyCString::strlen(lpsz); 
     m_buf = new char[len + 1]; 
     MyCString::strcpy(m_buf, lpsz); 
    } 
} 

テストが不要になり、失敗した場合に例外をスローも必要になります呼び出し元は、スローされる可能性のある例外をキャッチして処理します(std::bad_alloc)。

異なる形式の演算子newが使用されている場合でも、テストはまだ必要です。もちろん

#include <new> 

void String::_copy(const char* lpsz 
{ 
    if (lpsz != 0) 
    { 
     int len = MyCString::strlen(lpsz); 
     m_buf = new (std::nothrow) char[len + 1]; 
     if (m_buf) MyCString::strcpy(m_buf, lpsz); 
    } 
} 

、近代的なC++で、一つは通常Stringクラスを記述するために気にしないでしょう。 <string>からstd::stringの使用が好ましい。メモリ割り当てエラーが発生した場合、std::stringのデフォルトアロケータは例外をスローします。

+0

しかしあなたがsongyuanyaoの答えを見たら。 「新しいハンドラが返されなくなるか、nullポイントになるまで割り当ての試行を繰り返す」というメッセージが表示されます。例外をキャッチする必要はありませんか? 'std :: bad_alloc'をキャッチする必要がある場合はありますか? –

+0

新しいハンドラが返されない場合は、割り当ての試行が成功したか、または例外がスローされたことを意味します。例外が発生した場合にプログラムが終了するのを待っている場合は、例外をキャッチする必要はありません。何らかのリカバリーアクションを実行して実行を続行する場合(リソースのリカバリーなど)、例外をスローする原因となったアクションを再試行するには、例外をキャッチする必要があります。 – Peter

関連する問題