1

以下のコードで割り当てたポインタを削除する方法:

char* ptr;
ptr=new char(65);   // memory for one char is created and is assigned 'A'
strcpy(ptr,"asdf"); // how can string of length 4 chars are copied
delete ptr;         // why am I getting debug error of Heap corruption detected

Visual C++2005を使用しています

4

5 に答える 5

7

配列の代わりに単一の文字を割り当てています。使用する:

char* ptr;
ptr=new char[65];
strcpy(ptr,"asdf");
delete[] ptr;

現在のように、最初aは割り当てられたcharに書き込み、残りは割り当てられなかった任意のメモリに書き込みます。ランタイムは(デバッグビルドで)それを検出し、文句を言います。

私の答えの質問部分に私のコメントをする:

C ++には、質問のコードの潜在的なエラーを識別するメカニズムがありません。コンパイラが渡されるバッファのサイズを知る唯一の方法は、strcpy静的分析を使用することであり、それが機能する場合と機能しない場合があります。しかし、たとえそうだとしても、コンパイラはのセマンティクスを知りませんstrcpy。したがって、コンパイル時に、エラーについて警告することはできません。

現在、バッファがstrcpy実行時に渡されるとき、そのバッファstrcpyの大きさを知る方法はありません。したがって、呼び出し元が適切なバッファを提供したと想定し、コピーを続行します。運が良ければ、割り当てられたバッファをオーバーフローさせると、割り当てられていないページへの書き込みが原因ですぐにクラッシュします。そうしないと、メモリが破損します。

発生するエラーは、デバッグビルドで使用されるメカニズムの結果です。メモリマネージャーは、要求したバイトよりも数バイト多く割り当て、それらに特別なパターンを書き込みます。次に、割り当てられたメモリが解放されると、そのパターンがまだ存在するかどうかを確認します。そうでない場合は、ユーザーのコードが書き込まれていると文句を言います。リリースビルドでは、これらの追加のチェックはありません。そのようなバグは、気付かれることなく破損を引き起こす可能性があります。

このような場合を回避する唯一の方法は、より安全なコードを作成することです。

  1. のような高レベルの構造を使用しますstd::string。それらはあなたのためにメモリ管理を行い、低レベルの文字列関数を扱う必要からあなたを救います。
  2. Microsoftの(非標準の)安全なバリアント(たとえば、strcpy_s )を使用します。これらの関数はバッファのサイズも取得し、それが不十分な場合は失敗します-損傷を与えることはありません。
  3. (標準の)strncpyを使用し、最後の引数としてバッファーのサイズを渡し、戻り値をチェックして、コピーされた文字数を確認します。前の提案と同様に、間違ったバッファサイズを指定すると、損傷が発生します。
  4. 自分のつま先を撃ちたい場合は、C++が喜んで下向きの銃を手渡すことを覚えておいてください。生のバッファ、ポインタ、および低レベルの文字列関数の処理は注意して行う必要があります。言語はあなた自身の過ちからあなたを救うことはありません。
于 2012-07-12T11:20:48.660 に答える
4

これを行うことにより、4文字の「asdf」(nullターミネータをカウントする場合は実際には5文字)を1文字しか使用できないメモリブロックに詰め込もうとしてヒープを破損したためです。

strcpy(ptr,"asdf");

アップデート:

必要なだけ(またはそれ以上)のメモリを割り当てる必要があります。4文字の文字列をメモリブロックにコピーする必要がある場合は、メモリブロックがそれを保持するのに十分な大きさであることを確認する必要があるため、この場合は、

ptr=new char[5];

5char秒(文字列の4文字+すべての文字列の最後に1つのヌルターミネータが必要)を割り当て、割り当てられたメモリを解放するには、次を使用する必要があります。

delete[] ptr;

[]1文字だけでなく、文字の配列を削除することを意味します。

于 2012-07-12T11:21:34.663 に答える
1

それは実際には間違っています。あなたが欲しい:

ptr=new char[65];   // memory for one char is created and is assigned 'A'
strcpy(ptr,"asdf"); // how can string of length 4 chars are copied
delete[] ptr;   

より良い:

char ptr[65];
strcpy(ptr,"asdf");

一番:

std::string str("asdf");
于 2012-07-12T11:20:01.823 に答える
1

これは、メモリ破損の典型的なケースです。具体的にはヒープ。ptr1バイトが割り当てられており、その1バイトをオーバーフローさせる文字列コピー操作を実行しています。

プログラムは必ずしもすぐにクラッシュするわけではありませんが、ランダムなクラッシュや未定義の動作が発生する可能性があります。

于 2012-07-12T11:33:51.077 に答える
1

ptrまず、1バイトで割り当てます。それに「A」を割り当てました。

次に、サイズ5の文字列をptrusingにコピーしようとしましstrcpyた。

strcpy呼び出し自体でクラッシュしなかったのはなぜか疑問に思われるかもしれません。その理由はstrcpy、割り当てのサイズについて検証を実行しないため、バッファオーバーフローの結果として未定義の動作が発生するためです。

参照:strcpyのセグメンテーション違反

char* ptr;
ptr=new char[5];   // I see no point in assigning 'A' as you replace it in next statement.
strcpy(ptr,"asdf");
delete[] ptr;         // delete[] is used as memory is allocated for arrays of elements.

strcpyまた、Visual Studio 2005では、、の安全な代替手段を使用できますstrcpy_s

参照:strcpy_s、wcscpy_s、_mbscpy_s

于 2012-07-12T11:46:21.347 に答える