在软件会议中讨论之后,我已经着手查明是否删除带有普通delete
的动态分配的原语数组会导致内存泄漏。
我编写了这个小程序并使用在Windows XP上运行的visual studio 2008进行编译:
#include "stdafx.h"
#include "Windows.h"
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*1000; i++)
{
int* p = new int[1024*100000];
for (int j =0;j<BLOCK_SIZE;j++) p[j]= j % 2;
Sleep(1000);
delete p;
}
}
我比使用任务管理器监视我的应用程序的内存消耗,令人惊讶的是内存已正确分配和释放,分配的内存没有像预期的那样稳定增加
我已修改我的测试程序以分配非原始类型数组:
#include "stdafx.h"
#include "Windows.h"
struct aStruct
{
aStruct() : i(1), j(0) {}
int i;
char j;
} NonePrimitive;
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*100000; i++)
{
aStruct* p = new aStruct[1024*100000];
Sleep(1000);
delete p;
}
}
运行10分钟后,内存无意义增加
我编制了警告级别为4的项目并没有收到任何警告。
可视化工作室运行时是否可以跟踪分配的对象类型,以便在该环境中delete
和delete[]
之间没有区别?
答案 0 :(得分:19)
delete p,其中p是一个数组,称为未定义行为。
具体来说,当你分配一个原始数据类型数组(int)时,编译器没有很多工作要做,所以它把它变成一个简单的malloc(),所以delete p可能会起作用。
删除p通常会在以下情况下失败:
答案 1 :(得分:17)
不,这是未定义的行为。不要这样做 - 使用delete[]
。
在VC ++ 7到9中,它恰好工作when the type in question has trivial destructor,但它可能会停止在更新版本上运行 - 通常具有未定义行为的东西。不管怎么说都不要这样做。
答案 2 :(得分:3)
它被称为未定义的行为;它可能有用,但你不知道为什么,所以你不应该坚持下去。
我不认为Visual Studio会跟踪您如何分配对象(如数组或普通对象),并神奇地将[]
添加到您的删除中。它可能会将delete p;
编译为与您使用p = new int
分配的相同代码,并且正如我所说,由于某种原因它可以正常工作。 但你不知道为什么。
答案 3 :(得分:3)
答案是肯定的,它会导致内存泄漏,因为它不会为数组中的每个项调用析构函数。这意味着数组中项目拥有的任何额外内存都将泄漏。
更符合标准的答案是它是未定义的行为。例如,编译器完全有权对阵列使用不同的内存池而不是非阵列项。以新方式执行但删除另一方可能会导致堆损坏。
您的编译器可能会保证标准不会,但第一个问题仍然存在。对于没有额外内存的POD项目(或文件句柄等资源),您可能没问题。
即使它对您的编译器和数据项是安全的,也不要这样做 - 它也会误导任何试图阅读您的代码的人。
答案 4 :(得分:2)
不,在处理数组时应该使用delete[]
答案 5 :(得分:2)
仅使用delete
将不会调用数组中对象的析构函数。虽然它可能按预期工作但未定义,因为它们的确切工作方式存在一些差异。所以你不应该使用它,even for built in types。
答案 6 :(得分:1)
原因似乎不是泄漏内存是因为删除通常基于free,已经知道需要释放多少内存。但是,c ++部分不太可能正确清理。我打赌只会调用第一个对象的析构函数。
答案 7 :(得分:1)
使用delete with []告诉编译器在数组的每个项目上调用析构函数。 如果在使用动态内存分配的对象数组上使用,则不使用delete []会导致内存泄漏,如下所示:
class AClass
{
public:
AClass()
{
aString = new char[100];
}
~AClass()
{
delete [] aString;
}
private:
const char *aString;
};
int main()
{
AClass * p = new AClass[1000];
delete p; // wrong
return 0;
}