您的位置:首页 > 其它

new和delete时究竟发生了什么?

2007-05-28 09:22 302 查看
在C++中,当用户调用new和delete时,实际上分别发生了如下事情:

new:

1. 调用::operator new(相当于malloc), 分配一块内存;

2. 检查第一步内存分配的结果,如果未被正常分配(比如系统资源耗尽时),抛出异常,直接返回,接下来的步骤不会执行;

3. 调用构造函数.

delete:

1. 检查指定要删除的内存,如果已经为空,直接返回,接下来的步骤不会执行;

2. 调用析构函数;

3. 调用::operator delete(相当于free),释放内存.

下面我们通过查看测试代码的相应汇编代码来证实上述观点.

测试代码:


#include "stdafx.h"


#include <iostream>


using namespace std;




class MyClass




...{


public:




MyClass(const char*) ...{}




~MyClass() ...{}




operator char() ...{return 'a';}


protected:


private:


char* m_data;


};




int _tmain(int argc, _TCHAR* argv[])




...{


MyClass* my = new MyClass("Hello!");


delete my;




char memory[sizeof(MyClass)];


void* p = memory;


MyClass* second = new (p) MyClass("World!");


second->~MyClass();




return 0;


}



相应的汇编代码如下:


int _tmain(int argc, _TCHAR* argv[])




...{


004136E0 push ebp


……


MyClass* my = new MyClass("Hello!");


0041371D push 4


0041371F call operator new (411190h) // 步骤1


00413724 add esp,4


00413727 mov dword ptr [ebp-134h],eax


0041372D mov dword ptr [ebp-4],0


00413734 cmp dword ptr [ebp-134h],0


0041373B je wmain+75h (413755h) // 步骤2


0041373D push offset string "Hello!" (41676Ch)


00413742 mov ecx,dword ptr [ebp-134h]


00413748 call MyClass::MyClass (41116Dh) // 步骤3


0041374D mov dword ptr [ebp-148h],eax


00413753 jmp wmain+7Fh (41375Fh)


00413755 mov dword ptr [ebp-148h],0


0041375F mov eax,dword ptr [ebp-148h]


00413765 mov dword ptr [ebp-140h],eax


0041376B mov dword ptr [ebp-4],0FFFFFFFFh


00413772 mov ecx,dword ptr [ebp-140h]


00413778 mov dword ptr [ebp-14h],ecx


delete my;


0041377B mov eax,dword ptr [ebp-14h]


0041377E mov dword ptr [ebp-11Ch],eax


00413784 mov ecx,dword ptr [ebp-11Ch]


0041378A mov dword ptr [ebp-128h],ecx


00413790 cmp dword ptr [ebp-128h],0


00413797 je wmain+0CEh (4137AEh) // 步骤1


00413799 push 1


0041379B mov ecx,dword ptr [ebp-128h]


004137A1 call MyClass::`scalar deleting destructor' (41100Ah) // 步骤2和步骤3


004137A6 mov dword ptr [ebp-148h],eax


004137AC jmp wmain+0D8h (4137B8h)


004137AE mov dword ptr [ebp-148h],0




char memory[sizeof(MyClass)];


void* p = memory;


004137B8 lea eax,[ebp-20h]


004137BB mov dword ptr [ebp-2Ch],eax


MyClass* second = new (p) MyClass("World!");


004137BE mov eax,dword ptr [ebp-2Ch]


004137C1 push eax


004137C2 push 4


004137C4 call operator new (4111E0h) // 步骤1


004137C9 add esp,8


004137CC mov dword ptr [ebp-104h],eax


004137D2 mov dword ptr [ebp-4],1


004137D9 cmp dword ptr [ebp-104h],0


004137E0 je wmain+11Ah (4137FAh) // 步骤2


004137E2 push offset string "World!" (4166FCh)


004137E7 mov ecx,dword ptr [ebp-104h]


004137ED call MyClass::MyClass (41116Dh) // 步骤3


004137F2 mov dword ptr [ebp-148h],eax


004137F8 jmp wmain+124h (413804h)


004137FA mov dword ptr [ebp-148h],0


00413804 mov ecx,dword ptr [ebp-148h]


0041380A mov dword ptr [ebp-110h],ecx


00413810 mov dword ptr [ebp-4],0FFFFFFFFh


00413817 mov edx,dword ptr [ebp-110h]


0041381D mov dword ptr [ebp-38h],edx


second->~MyClass();


00413820 push 0


00413822 mov ecx,dword ptr [ebp-38h]


00413825 call MyClass::`scalar deleting destructor' (41100Ah)




return 0;


0041382A xor eax,eax


}


0041382C push edx


……



这里需要特别注意的是:

1. 定位创建(placement new)的方法, 即new(p) MyClass("Hello"),不管p是否被正确创建,定位创建的过程与一般创建的过程是一样的,即也经历3个主要步骤.

2. 汇编代码中所说的scalar deleting destructor是编译器自动生成的, 相当于先执行析构函数再执行delete操作,相关信息可参考http://www.thescripts.com/forum/thread263644.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: