正常代码:
class CTest
{
public:
~CTest(){}
private:
int m_value;
};
int main()
{
while (1)
{
CTest *p = new CTest[7];
delete[] p;
}
return 0;
}
对应的汇编:
while (1)
{
CTest *p = new CTest[7];
00251011 push 20h <span style="white-space:pre"> </span>;7*sizeof(CTest)=28,这里申请的是32字节大小
00251013 call operator new[] (25104Ah)
00251018 add esp,4
0025101B test eax,eax
0025101D je main+1 (251011h)
0025101F add eax,4
00251022 mov dword ptr [eax-4],7 <span style="white-space:pre"> </span>;多申请的4个字节,用来存放数组的个数。这个例子里是7
delete[] p;
00251029 je main+1 (251011h)
0025102B mov ecx,dword ptr [eax-4] <span style="white-space:pre"> </span>;ecx=7,给后面的delete[]使用
0025102E lea esi,[eax-4]
00251031 push offset CTest::~CTest (251000h)
00251036 push ecx
00251037 push 4
00251039 push eax <span style="white-space:pre"> </span>;p
0025103A call `eh vector destructor iterator' (2510C2h)
0025103F push esi <span style="white-space:pre"> </span>;原始地址,(char*)p - 4
00251040 call operator delete[] (251126h)
00251045 add esp,4
}
对于new[],vs2008是在申请内存的时候多申请了4个字节大小的内存,用来存放数组个数,返回给上层使用的是实际地址+4。
错误的delete:
class CTest
{
public:
~CTest(){}
private:
int m_value;
};
int main()
{
while (1)
{
CTest *p = new CTest[7];
delete p;
}
return 0;
}
对应的代码:
while (1)
{
CTest *p = new CTest[7];
001C1000 push 20h
001C1002 call operator new[] (1C1025h)
001C1007 add esp,4
001C100A test eax,eax
001C100C je main (1C1000h)
001C100E add eax,4
001C1011 mov dword ptr [eax-4],7
delete p;
001C1018 je main (1C1000h)
001C101A push eax
001C101B call operator delete (1C1040h) ;只调用了数组里面第一个成员的析构;传给下层的地址
001C1020 add esp,4
}
delete传给下层的指针是原始地址向后偏移了4字节,下层是无法识别的,下层只认识返回给new[]的原始地址,这块32字节内存不会释放。
vs2008下内存泄漏,vs2015直接崩。