C++ 调用free()或delete而不是delete[]是否有危险?

C++ 调用free()或delete而不是delete[]是否有危险?,c++,memory-management,free,new-operator,C++,Memory Management,Free,New Operator,可能重复: delete是否取消分配数组中第一个元素之外的元素 char *s = new char[n]; delete s; 在上述情况下,考虑到s的所有元素都是连续分配的,并且不能仅删除数组的一部分,这是否重要 对于更复杂的类型,delete会调用第一个类型之外的对象的析构函数吗 Object *p = new Object[n]; delete p; delete[]如何推断出超出第一个的对象的数量,这难道不意味着它必须知道分配的内存区域的大小吗?如果由于性能原因,内存区域被分配了

可能重复:

delete
是否取消分配数组中第一个元素之外的元素

char *s = new char[n];
delete s;
在上述情况下,考虑到
s
的所有元素都是连续分配的,并且不能
仅删除数组的一部分,这是否重要

对于更复杂的类型,
delete
会调用第一个类型之外的对象的析构函数吗

Object *p = new Object[n];
delete p;
delete[]
如何推断出超出第一个的
对象的数量,这难道不意味着它必须知道分配的内存区域的大小吗?如果由于性能原因,内存区域被分配了一些悬垂,会怎么样?例如,可以假设并非所有分配器都提供单个字节的粒度。然后,任何特定的分配都可能超过每个元素所需的大小一个或多个元素

对于基本类型,例如
char
int
,以下类型之间是否有任何区别:

int *p = new int[n];
delete p;
delete[] p;
free p;
除了通过
delete
->
free
解除分配机制进行的相应调用所采用的路由之外

对于基本类型,例如char、int,以下类型之间是否有任何区别:

int *p = new int[n];
delete p;
delete[] p;
free p;

我会说你会有不确定的行为。所以你不应该指望稳定的行为。您应该始终使用new/delete、new[]/delete[]和malloc/free对。

这是未定义的行为。因此,答案是:是的,可能有危险。而且不可能准确预测什么会引发问题。即使它能工作一次,它还能工作吗?这取决于类型吗?元素计数?

这是一种未定义的行为(很可能会立即损坏堆或使程序崩溃),您不应该这样做。仅使用与用于分配该内存的原语相对应的原语释放内存

违反此规则可能会巧合地导致正常运行,但一旦任何内容发生更改(编译器、运行时和编译器设置),程序都可能中断。你永远不应该依赖这种正常的功能,并期待它

delete[]
使用特定于编译器的服务数据来确定元素的数量。通常,当调用
new[]
时,会分配一个更大的块,在开始时存储号码,并向调用者提供存储号码后面的地址。无论如何,
delete[]
依赖于
new[]
分配的块,而不是其他任何东西。如果将除
new[]
之外的任何内容与
delete[]
配对,或者反之亦然,则会遇到未定义的行为。

阅读常见问题解答:

在上述情况下,s的所有元素都是连续分配的,并且不可能只删除数组的一部分,这是否重要

是的

delete[]如何推断出第一个之外的对象数,这是否意味着它必须知道分配的内存区域的大小

编译器需要知道。看


因为编译器存储这些信息


我的意思是编译器需要不同的
delete
s来生成适当的簿记代码。我希望现在一切都清楚了。

是的,这很危险

不要这样做

这将导致程序崩溃或更糟糕的行为

对于分配了
new
的对象,必须使用
delete

对于分配了
new[]
的对象,您必须使用
delete[]

对于使用
malloc()
calloc()
分配的对象,必须使用
free()


还要注意,对于所有这些情况,第二次删除/释放已经删除/释放的指针是非法的
free
也不能用null调用。用NULL调用
delete/delete[]
是合法的。

是的,这确实有实际的危险。即使撇开实施细节不谈,也要记住,
operator new/operator delete
operator new[]/operator delete[]
功能可以完全独立地替换。因此,明智的做法是将
new/delete
new[]/delete[]
malloc/free
等视为不同的、完全独立的内存分配方法,它们完全没有共同之处。

尽管从某种逻辑上看,您可以将new[]与free[]或delete混合使用,而不是delete[],这是在编译器相当简单的假设下进行的,即它将始终使用malloc()来实现新[]的内存分配

问题是,如果您的编译器有足够智能的优化器,它可能会看到没有与您创建的对象的新[]对应的“delete[]”。因此,它可能会假设它可以从任何地方获取内存,包括堆栈,以节省为新[]调用真正malloc()的成本。然后,当您尝试调用free()或对其执行错误类型的删除时,它可能会出现严重故障

delete是否取消分配元素 超过数组中的第一个

char *s = new char[n];
delete s;
否。无论在哪个编译器上执行此操作,delete都将仅取消分配第一个元素。它在某些情况下可能有效,但这是附带的

在上述情况下,s的所有元素都已分配,这是否重要 连续,并且不应该只删除数组的一部分

取决于内存标记为空闲的方式。同样取决于执行情况

对于更复杂的类型,delete会调用第一个类型之外的对象析构函数吗

Object *p = new Object[n];
delete p;
不,试试这个:

#include <cstdio>

class DelTest {
    static int next;
    int i;
public:
    DelTest() : i(next++) { printf("Allocated %d\n", i); }
    ~DelTest(){ printf("Deleted %d\n", i); }
};

int DelTest::next = 0;

int main(){
    DelTest *p = new DelTest[5];
    delete p;
    return 0;
}
#包括
类DelTest{
静态int-next;
int i;
公众:
DelTest():i(next++){printf(“已分配%d\n”,i);}
~DelTest(){printf(“已删除%d\n”,i);}
};
int DelTest::next=0;
int main(){
DelTest*p=新的DelTest[5];