C++ 新建/删除和字符 *

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13247126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:07:10  来源:igfitidea点击:

c++ new/delete and char *

c++charnew-operator

提问by a3dsfcv

Can anyone help me, why I'm getting an error message while trying to free the allocated memory: Heap corruption detected. CTR detected the application wrote the memory after end of heap buffer.

任何人都可以帮助我,为什么我在尝试释放分配的内存时收到错误消息:检测到堆损坏。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;
}

回答by Alok Save

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

Causes Undefined behavior(UB).
You are writing beyond the bounds of allocated memery. You allocated enough memory for 5characters but your string has 6characters including the \0.

导致未定义行为(UB)
您正在写入超出分配内存的范围。您为5字符分配了足够的内存,但您的字符串包含6字符,包括\0.

Once your program has caused this UB, all bets are off and any behavior is possible.

一旦你的程序导致了这个 UB,所有的赌注都会被取消,任何行为都是可能的。

You need:

你需要:

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

In fact the ideal solution is to use std::stringand not char *. These are precisley the mistakes which std::stringavoids. And there is no real need of using char *instead of std::stringin your example.
With std::string:

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

  • You don't need to newanything
  • You don't need to deleteanything &
  • You can do everything with std::string, that you do with char *.
  • 你不需要new任何东西
  • 你不需要delete任何 &
  • 你可以做任何事情std::string,你做的char *

回答by JohnB

new char [strlen(s)];does not count the closing \0character, so your buffer is too short by one character.

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

回答by ecatmur

strcpyincludes the null terminator; strlendoes not. Write:

strcpy包括空终止符;strlen才不是。写:

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

回答by iabdalkader

From man strcpy(3):

来自 man strcpy(3)

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest.

strcpy() 函数将 src 指向的字符串(包括终止空字节 ('\0'))复制 到 dest 指向的缓冲区。

So you need to reserve 6bytes 5for the string and 1for the NULLbyte

所以,你需要储备6字节5的字符串,并1NULL字节

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

回答by Olaf Dietsche

All answers so far have addressed either the first or the second allocation. To sum up, there are twochanges you must make:

到目前为止,所有答案都涉及第一次分配或第二次分配。总而言之,您必须进行两项更改:

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

In both cases, you must allocate enough space for the string plus one byte for the terminating '\0'.

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

As others already pointed out, with c++ it's easier and safer to use std::string. No fuss with allocation and release of memory or paying attention to '\0' bytes:

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

and if it's just copying the string:

如果它只是复制字符串:

std::string s("hello");
std::string s2(s);

回答by ChrisW

You need to specify char *s1 = new char [strlen(s) + 1];to make room for the '\0'which terminates the string.

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

回答by Sergei Nikulov

You've corrupted s2 pointer by

你已经损坏了 s2 指针

strcpy(s, "hello");

Because s has size 5, while you've missed that strcpy includes string terminator.

因为 s 的大小为 5,而您已经错过了 strcpy 包含字符串终止符。

回答by Component 10

Your initial string sis only five characters long so can't be null terminated. "hello"will be copied by strcpyincluding the null-terminator but you'll have overrun the buffer. The strlenneeds it to be null terminated so if the null's not there, you'll have problems. Try changing this line:

您的初始字符串s只有五个字符长,因此不能以空字符结尾。"hello"将通过strcpy包含空终止符来复制,但您将溢出缓冲区。在strlen需要它是空终止,所以如果空不在那里,你就会有问题。尝试更改此行:

char *s = new char [6];

char *s = 新字符 [6];

Better still, prefer std::stringto C style string functions - they're just as efficient and a lot safer and easier to use. Also, try to avoid newand deleteunless you really have to use them. The problems you're getting are very common and can easily be avoided.

更好的是,更喜欢std::stringC 风格的字符串函数 - 它们同样高效,更安全,更易于使用。此外,尽量避免newdelete除非你真的必须使用它们。您遇到的问题非常普遍,很容易避免。