new/delete运算符代码分析

今天在测试程序测试的过程中,发现用new运算符申请空间失败,跟踪并分析了一下new的源码

1. 调用堆栈
new/delete运算符代码分析_第1张图片


2. operator new[]的代码

void *__CRTDECL operator new(size_t) /*_THROW1(std::bad_alloc)*/;

void * operator new[]( size_t cb )
{
    void *res = operator new(cb);

    RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));

    return res;
}

 

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
        {       // try to allocate size bytes
        void *p;
        while ((p = malloc(size)) == 0)      //申请空间
                if (_callnewh(size) == 0)    //若申请失败则调用处理函数
                {       // report no memory
                static const std::bad_alloc nomem;
                _RAISE(nomem);    //  #define _RAISE(x)	::std:: _Throw(x) 抛出nomem的异常
                }

        return (p);
        }

3. 原本我们的理解是,利用new运算符去创建对象,会做如下工作:
申请内存空间
调用对象的构造函数初始化对象
返回对象类型的指针

但是我们在源码中发现new中只是做了申请内存空间的工作,那作用不是跟MALLOC一样嘛,就多了个异常处理的功能。

现在一段示例代码:

class Test
{
   public:
	Test()
	{
	  cout<<"Constructor Test"<<endl;
	}

	~Test()
	{
	  cout<<"Destructor Test"<<endl;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	Test* p = new Test();
	delete p; 
        
        Test* p1 = new Test[10];
	delete []p1;
        return 0; }

看下红色语句对应的汇编代码:来分析一下这些语句究竟干了什么?
Test* p = new Test();
004114ED  push        1                              //1是对象大小,将参数入栈
004114EF  call        operator new (4111EFh)         //调用operator new()函数
004114F4  add         esp,4 
004114F7  mov         dword ptr [ebp-110h],eax       //eax中存放的是申请到的空间的内存首地址
004114FD  mov         dword ptr [ebp-4],0 
00411504  cmp         dword ptr [ebp-110h],0         //判断指针是否为NULL(ebp-110h)
0041150B  je          wmain+70h (411520h) 
0041150D  mov         ecx,dword ptr [ebp-110h]        //内存空间的地址存放与ecx寄存器中
00411513  call        Test::Test (4111C7h)            //调用Test类构造函数
00411518  mov         dword ptr [ebp-124h],eax 
0041151E  jmp         wmain+7Ah (41152Ah) 
00411520  mov         dword ptr [ebp-124h],0 
0041152A  mov         eax,dword ptr [ebp-124h] 
00411530  mov         dword ptr [ebp-11Ch],eax 
00411536  mov         dword ptr [ebp-4],0FFFFFFFFh 
0041153D  mov         ecx,dword ptr [ebp-11Ch] 
00411543  mov         dword ptr [ebp-14h],ecx 

虽然不是所有的代码都能看懂,但是关键地方的代码加上注释还是能看懂的哈。

delete p的汇编:

delete p;
00411B16  mov         eax,dword ptr [ebp-14h] 
00411B19  mov         dword ptr [ebp-0E0h],eax 
00411B1F  mov         ecx,dword ptr [ebp-0E0h] 
00411B25  mov         dword ptr [ebp-0ECh],ecx 
00411B2B  cmp         dword ptr [ebp-0ECh],0 
00411B32  je          wmain+0C9h (411B49h) 
00411B34  push        1    
00411B36  mov         ecx,dword ptr [ebp-0ECh] 
00411B3C call        Test::`scalar deleting destructor' (41125Dh) 
00411B41  mov         dword ptr [ebp-10Ch],eax 
00411B47  jmp         wmain+0D3h (411B53h) 
00411B49  mov         dword ptr [ebp-10Ch],0 

代码 Test::`scalar deleting destructor'其实是调用析构函数并释放空间的功能。

call   Test::~Test ()     // 调用类的析构函数
.......
call   operator delete ()  //这里由编译器负责调用了operator delete

 

对象数组的创建

Test* p1 = new Test[10];
004115E3  push        0Eh  
004115E5  call       operator new[] (4110F0h) //负责对象的空间申请 
004115EA  add         esp,4 
004115ED  mov         dword ptr [ebp-104h],eax 
004115F3  mov         dword ptr [ebp-4],1 
004115FA  cmp         dword ptr [ebp-104h],0 
00411601  je          wmain+12Dh (41163Dh) 
00411603  mov         eax,dword ptr [ebp-104h] 
00411609  mov         dword ptr [eax],0Ah 
0041160F  push        offset Test::~Test (41107Dh) //析构函数地址
00411614  push        offset Test::Test (4111EAh)  //构造函数地址
00411619  push        0Ah  
0041161B  push        1    
0041161D  mov         ecx,dword ptr [ebp-104h] 
00411623  add         ecx,4 
00411626  push        ecx  
00411627  call        `eh vector constructor iterator' (41119Ah) //对10个对象依次调用构造函数  
0041162C  mov         edx,dword ptr [ebp-104h] 
00411632  add         edx,4 
00411635  mov         dword ptr [ebp-148h],edx 
0041163B  jmp         wmain+137h (411647h) 
0041163D  mov         dword ptr [ebp-148h],0 
00411647  mov         eax,dword ptr [ebp-148h] 
0041164D  mov         dword ptr [ebp-110h],eax 
00411653  mov         dword ptr [ebp-4],0FFFFFFFFh 
0041165A  mov         ecx,dword ptr [ebp-110h] 
00411660  mov         dword ptr [ebp-20h],ecx 

 

对象数组的申请释放:

delete []p1;
00411663  mov         eax,dword ptr [ebp-20h] 
00411666  mov         dword ptr [ebp-0ECh],eax 
0041166C  mov         ecx,dword ptr [ebp-0ECh] 
00411672  mov         dword ptr [ebp-0F8h],ecx 
00411678  cmp         dword ptr [ebp-0F8h],0 
0041167F  je          wmain+186h (411696h) 
00411681  push        3    
00411683  mov         ecx,dword ptr [ebp-0F8h] 
00411689  call        Test::`vector deleting destructor' (41105Ah)//对10个对象依次调用析构函数
0041168E  mov         dword ptr [ebp-148h],eax 
00411694  jmp         wmain+190h (4116A0h) 
00411696  mov         dword ptr [ebp-148h],0 

1

你可能感兴趣的:(C++,new/delete)