21

割り当てられたメモリを解放しようとしているときにエラーメッセージが表示されるのはなぜですか。ヒープの破損が検出されました。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;
}
4

8 に答える 8

50
char *s = new char [5];
strcpy(s, "hello");

Undefined behavior(UB)の原因となります。
割り当てられたメモリの範囲を超えて書いています。文字に十分なメモリを割り当てまし5たが、文字列に6\0.

プログラムがこの UB を引き起こすと、すべての賭けはオフになり、あらゆる動作が可能になります。

必要なもの:

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

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

  • newあなたは何もする必要はありません
  • あなたは何もする必要はありませんdelete&
  • でできることはすべて で行うことができstd::stringますchar *
于 2012-11-06T08:29:50.293 に答える
13

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

于 2012-11-06T08:29:32.563 に答える
9

strcpynull ターミネータが含まれます。strlenではない。書く:

char *s1 = new char [strlen(s) + 1];
于 2012-11-06T08:29:41.627 に答える
6

man strcpy(3)から:

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

したがって、文字列と6バイト用にバイトを予約する必要があります51NULL

char *s = new char [6];
strcpy(s, "hello");
于 2012-11-06T08:30:20.443 に答える
3

これまでのすべての回答は、最初または 2 番目の割り当てのいずれかに対応しています。要約すると、2 つの変更を行う必要があります。

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);
于 2012-11-06T08:43:10.860 に答える
1

s2ポインターを破損しました

strcpy(s, "hello");

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

于 2012-11-06T08:32:55.150 に答える
1

文字列を終了するchar *s1 = new char [strlen(s) + 1];のためのスペースを確保するために指定する必要があります。'\0'

于 2012-11-06T08:30:17.293 に答える
0

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

char *s = 新しい文字 [6];

さらに良いことstd::stringに、C スタイルの文字列関数を使用することをお勧めします。C スタイルの文字列関数は、同じくらい効率的で、より安全で使いやすいものです。また、実際に使用する必要がない限りnew、 andを避けるようにしてください。delete発生している問題は非常に一般的であり、簡単に回避できます。

于 2012-11-06T08:29:50.800 に答える