web-dev-qa-db-ja.com

c ++ new / deleteおよびchar *

割り当てられたメモリを解放しようとしているときにエラーメッセージが表示される理由:ヒープの破損が検出されました。 CTRは、ヒープバッファの終了後にアプリケーションがメモリを書き込んだことを検出しました。

char *ff (char *s){
    char *s1 = new char [strlen(s)];
    strcpy(s1, s);
    return s1;
}

int _tmain(int argc, _TCHAR* argv[])
{
    char *s = new char [5];

    strcpy(s, "hello");
    char *s2 = ff(s);

    delete []s;     // This works normal
    delete []s2;    // But I get an error on that line
    return 0;
}
17
a3dsfcv
char *s = new char [5];
strcpy(s, "hello");

原因未定義の動作(UB)
あなたは割り当てられた記憶の範囲を超えて書いています。 5文字に十分なメモリを割り当てましたが、文字列には6を含む\0文字が含まれています。

プログラムでこのUBが発生すると、すべての賭けはオフになり、あらゆる行動が可能になります。

必要なもの:

char *s = new char [strlen("hello") + 1];

実際、理想的な解決策はstd::stringではなくchar *を使用することです。これらは、std::stringが回避する間違いの間違いです。また、あなたの例では、char *の代わりにstd::stringを使用する必要はありません。
with std::string

  • new何もする必要はありません
  • delete何もする必要はありません&
  • std::stringでできることはすべて、char *でできます。
44
Alok Save

new char [strlen(s)];は終了\0文字をカウントしないため、バッファーが1文字分短すぎます。

13
JohnB

strcpyにはヌルターミネータが含まれます。 strlenはしません。書く:

char *s1 = new char [strlen(s) + 1];
9
ecatmur

男から strcpy(3)

Strcpy()関数は、srcが指す文字列を、終端のヌルバイト( '\ 0')を含めて、destが指すバッファにコピーします。 。

したがって、予約する必要があります6バイト5は文字列、1NULLバイト

char *s = new char [6];
strcpy(s, "hello");
6
iabdalkader

これまでのすべての回答は、最初の割り当てまたは2番目の割り当てのいずれかに対処しています。まとめると、two変更が必要です:

char *s1 = new char [strlen(s) + 1];
...
char *s = new char [5 + 1];

どちらの場合も、文字列に十分なスペースを割り当てる必要がありますプラス終了 '\ 0'に1バイト

他の人がすでに指摘したように、c ++ではstd::stringを使用する方が簡単で安全です。メモリの割り当てと解放、または「\ 0」バイトに注意を払うことで大騒ぎしません。

std::string ff (const std::string &s){
    std::string s1(s);
    // do something else with s1
    return s1;
}

int main(int argc, char* argv[])
{
    std::string s("hello");
    std::string s2 = ff(s);
    return 0;
}

そして、それが単に文字列をコピーしている場合:

std::string s("hello");
std::string s2(s);
3
Olaf Dietsche

char *s1 = new char [strlen(s) + 1];を指定して、'\0'は文字列を終了します。

1
ChrisW

最初の文字列sは5文字しかないため、nullで終了することはできません。 "hello"は、ヌルターミネータを含むstrcpyによってコピーされますが、バッファがオーバーランします。 strlenはnullで終了する必要があるため、nullが存在しない場合は問題が発生します。この行を変更してみてください:

char * s = new char [6];

さらに良いのは、std::stringからCスタイルの文字列関数-同様に効率的で、はるかに安全で使いやすいです。また、本当に使用する必要がない限り、newdeleteを避けるようにしてください。発生している問題は非常に一般的であり、簡単に回避できます。

0
Component 10

S2ポインターが破損しています

strcpy(s, "hello");

Sのサイズは5であるため、strcpyには文字列ターミネーターが含まれていることを見逃しています。

0
Sergei Nikulov