C 新/删除和char *

c++ new/delete and char *

本文关键字:char 删除      更新时间:2023-10-16

任何人都可以帮我吗,为什么我在试图释放分配的内存时收到错误消息:检测到的堆损坏。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;
}
char *s = new char [5];
strcpy(s, "hello");

原因未定义的行为(UB)
您的写作超出了分配的模因的范围。您为5字符分配了足够的内存,但是您的字符串具有6字符,包括

一旦您的程序引起了此UB,所有赌注都关闭了,任何行为都是可能的。

您需要:

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

实际上理想的解决方案是使用std::string而不是char * 。这些是std::string避免的错误。在您的示例中,实际上不需要使用char *而不是std::string
使用std::string

  • 您不需要new
  • 您不需要delete任何东西&
  • 您可以使用std::string进行所有操作,您可以使用char *

new char [strlen(s)];不计算闭合字符,因此您的缓冲区太短了一个字符。

strcpy包括null终端;strlen没有。写:

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

来自Man Strcpy(3):

strcpy()函数复制了src指向的字符串, 包括终止null字节(' 0'),指向缓冲区 dest。

因此,您需要为字符串保留6字节5,而1 NULL字节

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

到目前为止,所有答案都解决了第一个或第二个分配。总而言之,您必须进行两个更改:

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

在这两种情况下,您都必须为字符串分配足够的空间加一个字节以终止' 0''

正如其他人已经指出的那样,使用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);

您需要指定char *s1 = new char [strlen(s) + 1];以腾出终止字符串的''

您已经通过

损坏了S2指针
strcpy(s, "hello");

因为S的尺寸为5,而您错过了strcpy包括字符串终结器。

您的初始字符串s只有五个字符长,因此无法终止。"hello"将由strcpy复制在内,包括null末端,但您将超越缓冲区。strlen需要将其终止终止,因此,如果不存在,则会出现问题。尝试更改此行:

char *s = new char [6];

更好的是,更喜欢std::string而不是C样式字符串功能 - 它们同样有效,更安全,更易于使用。另外,除非您确实必须使用它们,否则请尝试避免使用newdelete。您得到的问题非常普遍,可以轻松避免。