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];