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

CStrings and pointers: Heap corruption when trying to delete a character array

我用谷歌搜索这个已经筋疲力尽,但我一直无法找到明确的答案或帮助自己理解出了什么问题。作为家庭作业的一部分,我试图为字符数组(即 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?

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

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!

似乎通过赋值来初始化数组对我来说有点破坏。

有人可以帮我吗?

您正在尝试删除 "September" 所在的内存块,并且它肯定没有分配到堆中,如果您需要初始化预分配缓冲区,请使用 strcpy(..) 函数。

这是您问题的根源:

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 数组分配 [=22 的值来分配非堆内存(数据段内存,如果准确的话) =] 就可以了。

您尝试删除非堆内存,然后出现错误。

使用 strcpy(chPtr,"September") 甚至更好:去掉 C 并使用 std::string.

作业 chPtr = "September"; 与您认为的不同。它将静态字符数组 "September" 地址 分配给变量 chPtr。当您尝试对其调用 operator delete[] 时,出现了错误:您正在尝试删除静态分配的字符数组。

如果你想复制个字符,你将不得不使用像std::strcpy.

这样的字符串复制函数

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

chPtr = "September"; 更改 chPtr 指向的位置。它不再指向分配 10 char 的数组的任何位置,而是指向静态字符数组 "September"。然后您尝试删除它,但失败了。

作为测试,您可以试试这个:

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;

chPtr = "September" 不会将任何内容分配给 chPtr 指向的内存,而是将 chPtr 分配给指向确实包含 "September" 的其他内存。你不能删除这段记忆。