VC中的delete和delete[]
很多人在考虑delete和delete[]总是区分基本数据类型和用户自定义类型
但是我发现并非如此
int * p = new int[100];
我们调用delete p和delete[] p并没有任何问题,也检查不出内存泄漏
class A
{
public:
int a;
A( ) { }
};
A * p = new A[100];
我们调用delete p和delete[] p同样也没有任何问题,也检查不出内存泄漏
class A
{
public:
int a;
A( ) { }
~A( ) { }
};
A * p1 = new A[100];
A * p2 = new A;
我们调用delete p2和delete[] p1也没有任何问题,没有内存泄漏
但是我们调用delete p1和delete[] p2就立即出错
跟踪发现
void* __cdecl operator new[](size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
{
return ::operator new(nSize, nType, lpszFileName, nLine);
}
void __cdecl operator delete[](void* p)
{
::operator delete(p);
}
从上面的代码来看,new[]就是调用了new,delete[]也同样就是调用delete,为什么会出错呢,检查发现Debug下VC做了一些CRT断言,问题就出在_CrtIsValidHeapPointer这个函数上,这个函数是有源代码的,但不能跟踪无法发现错误,只能看到该函数返回出栈时出错。
那原因究竟在哪?
大家可以看到问题就在那个定义了的析购函数上。
还是继续跟踪有析购函数和无析购函数的情况
class A // 有析购函数
{
public:
int a;
A( ) { }
~A( ) { }
};
class B // 无析购函数
{
public:
int b;
B( ) { }
};
A * p1 = new A[1];
A * p2 = new A;
B * p3 = new B[1];
B * p4 = new B;
跟踪进去,你会发现
p1申请了8个字节
p2申请了4个字节
p3申请了4个字节
p4申请了4个字节
而p1使用delete直接删除就会出错,原因是内存长度不一致,那么多出来的这4个字节做什么用呢,我并没有继续跟下去,我想我差不多能猜出来了,这多出来的指针 。。。