CStrings和指针:尝试删除字符数组时堆损坏

时间:2015-05-31 20:48:26

标签: c++ arrays pointers c-strings

我已经用尽了谷歌搜索这个,但我无法找到明确的答案或帮助自己了解出了什么问题。作为家庭作业的一部分,我正在尝试为字符数组(即CString)动态分配内存,并指定一个char指针变量指向它,然后在我结束程序之前删除分配的内存。我只是把我的头围绕在指针上,所以我怀疑我对幕后发生的事情的一些理解是不正确的,而我最终得到的是Visual Studio 2010给我的堆腐败断点。

以下是我正在尝试做的简化版本(我的评论表明我想的我在做什么):

char *chPtr = new char[10]; // Create a char pointer type variable, and point it at the memory allocated for a char array of length 10
chPtr = "September";        // Assign 9 characters (+1 null terminator character) to the char array
cout << chPtr;              // Prints "September", then finds the null terminator and stops printing
delete [] chPtr;            // THIS is what causes my heap corruption -> But I don't know why. Shouldn't this delete the array of memory that chPtr is pointing at?
  • 我也尝试过使用delete chPtr,并使用相同的堆损坏结果。
  • 我尝试手动将空终止符分配给数组chPtr[9] = '\0';的末尾,但这也会导致堆损坏。为什么?当我做cout << chPtr[7];之类的事情而没有任何问题时,我可以从数组中访问单个字符......

真正令人困惑的是,这种方法没有错误:

char *chPtr = new char[10]; // As above, create a char pointer type and point it at the memory allocated for a char array of length 10
delete chPtr;               // This doesn't give any error!

似乎通过赋值来初始化数组对我来说是一件坏事。

有人可以帮帮我吗?

5 个答案:

答案 0 :(得分:1)

chPtr = "September";更改chPtr指向的位置。它不是指向分配了10 char的数组的任何地方,而是指向静态字符数组&#34; 9月&#34;。然后你试图删除那个失败的。

作为测试,您可以尝试:

char* p = nullptr;
std::cout << static_cast<void*>(p) << "\n";

p = new char[10];
std::cout << static_cast<void*>(p) << "\n";

p = "September";
std::cout << static_cast<void*>(p) << "\n";

可能的输出是:

00000000
0068C988
00D18B34

您可以看到p指向的地址在每次分配时都会发生变化。在免费商店(0068C988)上分配的块在第三次分配时丢失。

如果要分配字符,请执行

之类的操作
std::strcpy(chPtr, "September");

这包含了内存管理,数组和指针的所有注意事项。你真正想做的是:

std::string s = "September";
std::cout << s;

答案 1 :(得分:0)

您正试图删除您的&#34;九月&#34;如果你需要初始化预先分配的缓冲区使用strcpy(..)函数,那么它的位置肯定不会在堆中分配。

答案 2 :(得分:0)

这是您问题的根源:

char *chPtr = new char[10]; // Create a char pointer type variable, and point it at the memory allocated for a char array of length 10
chPtr = "September";  

首先在chPtr上分配堆内存,然后通过为非堆char数组赋值&#34; september&,分配非堆内存(数据段内存,如果要准确) #34;在它上面。

您尝试删除非堆内存,然后就会收到错误。

使用strcpy(chPtr,"September")甚至更好:丢失C并使用std::string

答案 3 :(得分:0)

作业chPtr = "September";并没有按照您的想法行事。它将静态字符数组"September"地址分配给变量chPtr。当您尝试在其上调用operator delete[]时,出现问题:您正在尝试删除静态分配的字符数组。

如果您希望复制字符,则必须使用std::strcpy之类的字符串复制功能。

当然,在C ++中使用C风格字符串的正确方法是不使用C风格的字符串。使用标准C ++ std::basic_string模板之一。

答案 4 :(得分:0)

chPtr = "September"并没有为chPtr所指向的内存分配任何内容,而是指定chPtr指向其他一些确实存在的内存&#34; 9月和#34 ;。你不能删除这个记忆。