cstring和指针:试图删除字符数组时堆损坏

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

本文关键字:数组 字符 损坏 删除 指针 cstring      更新时间:2023-10-16

我已经用尽自己的谷歌这个,但我没有能够找到一个明确的答案或帮助自己理解什么是错的。作为家庭作业的一部分,我试图动态分配内存的字符数组(即。一个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,具有相同的堆损坏结果。
  • 我已经尝试手动分配null终止符到数组chPtr[9] = '';的末尾,但这也会导致堆损坏。为什么?当我做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!

通过赋值来初始化数组似乎在某种程度上破坏了我的工作。

有人能帮我一下吗?

chPtr = "September";改变chPtr指向的位置。它现在指向静态字符数组"September",而不是指向分配了10个char s的数组的位置。然后您试图删除它,但失败了。

作为测试,您可以这样做:

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;

这就是你的问题的根源:

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上分配一个堆内存,然后通过赋值为"september"的非堆char数组分配一个非堆内存(数据段内存)。

你尝试删除非堆内存,然后你得到你得到的错误。

使用strcpy(chPtr,"September")或者更好:丢掉C,使用std::string

你正试图删除一块内存,你的"九月"所在的地方,它肯定不是分配在堆,如果你需要初始化预分配的缓冲区使用strcpy(..)函数

chPtr = "September"没有给chPtr所指向的内存赋值,而是将chPtr赋值给其他存放"September"的内存。你不能删除这个内存

赋值chPtr = "September";并不像你想象的那样。它将静态字符数组"September"地址赋值给变量chPtr。当您尝试在它上调用operator delete[]时,事情出错了:您试图删除静态分配的字符数组。

如果希望复制字符,则必须使用类似std::strcpy的字符串复制函数。

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