以前没重载过操作符new和delete,最近由于项目需要,写了个试试.本以为手到擒来,没想到还遇到不少问题.
{
public:
CTestNew()
{
AtlTrace(_T("CTestNew\n"));
}
~CTestNew()
{
AtlTrace(_T("~CTestNew\n"));
}
void* operator new (size_t size)
{
AtlTrace(_T("operator new\n"));
void* p = malloc(size);
return p;
}
void operator delete (void* p)
{
AtlTrace(_T("operator delete\n"));
free(p);
}
};
当调用如下代码:
CTestNew *p = new CTestNew;
delete p;
其输出是:
operator new
CTestNew
~CTestNew
operator delete
这都没发现什么问题.但是我平时写代码一般先不写实现,直接返回NULL的。于是问题出来了.修改一下new的重载代码:
void* operator new (size_t size)
{
AtlTrace(_T("operator new\n"));
return NULL;
}
再次调用时只输出:operator new
构造函数、析构函数、operator delete函数都没调用。出乎我意料之外。
反汇编跟踪了一下:
//当调用operator new 函数时,其把函数的返回值保存在eax寄存器中
0043A794 call CTestNew::operator new (4367DAh)
0043A799 add esp,4
0043A79C mov dword ptr [ebp-104h],eax
0043A7A2 mov dword ptr [ebp-4],0
//与0做比较 如果相等 就跳转到0043A7C5处,因此跳过了执行构造函数CTestNew
0043A7A9 cmp dword ptr [ebp-104h],0
0043A7B0 je CMainDlg::OnOK+75h (43A7C5h)
0043A7B2 mov ecx,dword ptr [ebp-104h]
//执行构造函数
0043A7B8 call CTestNew::CTestNew (436672h)
0043A7BD mov dword ptr [ebp-118h],eax
0043A7C3 jmp CMainDlg::OnOK+7Fh (43A7CFh)
0043A7C5 mov dword ptr [ebp-118h],0
0043A7CF mov eax,dword ptr [ebp-118h]
0043A7D5 mov dword ptr [ebp-110h],eax
0043A7DB mov dword ptr [ebp-4],0FFFFFFFFh
0043A7E2 mov ecx,dword ptr [ebp-110h]
0043A7E8 mov dword ptr [ebp-20h],ecx
delete p;
0043A7EB mov eax,dword ptr [ebp-20h]
0043A7EE mov dword ptr [ebp-0ECh],eax
0043A7F4 mov ecx,dword ptr [ebp-0ECh]
0043A7FA mov dword ptr [ebp-0F8h],ecx
//一路跟踪 此时ebp-0F8h地址处的值正是operator new 函数的返回值
//与0做比较 如果相等 就跳转到0043A81E处,因此跳过了执行析构函数~CTestNew和operator delete函数
0043A800 cmp dword ptr [ebp-0F8h],0
0043A807 je CMainDlg::OnOK+0CEh (43A81Eh)
0043A809 push 1
0043A80B mov ecx,dword ptr [ebp-0F8h]
0043A811 call CTestNew::`scalar deleting destructor' (437770h)
0043A816 mov dword ptr [ebp-118h],eax
0043A81C jmp CMainDlg::OnOK+0D8h (43A828h)
0043A81E mov dword ptr [ebp-118h],0