删除char数组

DaC*_*own 23 c++ memory-management

这个问题关系到这一个.鉴于此代码:

char *p = new char[200];
delete[] p;
Run Code Online (Sandbox Code Playgroud)

如果你p[100] = '\0'在删除p之前设置会发生什么?

我有一些代码,当我试图删除一个非空终止的char数组时,我收到了一个调试错误,这是关于删除未分配的堆内存.它似乎从数组的边界中删除了内存.

小智 40

代码:

char *p = new char[200];
p[100] = '\0';
delete[] p;
Run Code Online (Sandbox Code Playgroud)

是完全有效的C++.delete不知道或不关心以null结尾的字符串,因此您的错误必须有其他原因.

  • @Nazeeh你可能在这里学到了一些错误,或者可能没有完全引用你对它的理解.在大小为10的数组中,第10个元素是第9个索引,而不是10个,如果你在第10个索引上写任何东西,你已经损坏了堆,调用delete来崩溃你的应用程序是无关紧要的,你的应用程序必然会崩溃无论如何,这只是时间问题.在你的错误后立即调用删除只是你很幸运,你必须尽快看到错误(并在一个更简单的用例),而不是必须经历一个凌乱的细节来发现这个错误. (13认同)
  • _“删除不知道或不关心空终止...”_这不是真的。如果你有`p[2]`,那么你不小心设置了`p[2]='\0'`,删除`p`会给出一个与内存相关的错误,显然是因为删除p[2]处的内存是尝试过。 (2认同)

Joh*_*itb 8

什么都不会发生.您可以在分配的内存中间的某个位置写入(与启动相隔100个字节,在分配的内存结束之前的99个字节).

然后你将释放分配的内存.编译器将完全按照我们的预期处理它.由此分配的内存与空终止字符串完全无关.你可以将你想要的一切都粘在那个记忆中.它是一些"原始"存储空间,你甚至可以在该内存中创建一些任意的C++对象(placement new).

你的错误在别的地方.例如,一个常见的错误是这一个,其中构造函数被调用一次,但析构函数被调用两次,双重删除:

struct A { P *p; A() { p = new P; } ~A() { delete p; } };
A getA() { return A(); } int main() { A a = getA(); }
Run Code Online (Sandbox Code Playgroud)

现在,发生的是默认构造函数被调用一次,并且创建的对象被复制零次或多次.但是为每个创建的副本运行析构函数.因此,您将多次调用指针上的析构函数,从而导致此类奇怪的错误.解决这个问题的正确方法是使用智能指针shared_ptr.作为练习,您也可以通过编写适当的复制构造函数来复制对象并在复制构造函数中分配内存,以便复制和相应的原始对象保持不同的指针.


Jar*_*Par 6

我认为你将一个普通的旧char数组与一个代表C风格字符串的char数组混淆.C++ delete运算符不关心C样式字符串数组.所有它将看到的是一系列字符.这与删除int数组完全没什么不同.

null终止符的存在与否仅与将char*C样式字符串视为C样式的函数相关.