c++ 反汇编 构造函数和析构函数

构造函数和析构函数出现的时机

  • 局部对象
   109:     // 局部对象定义调用构造函数
   110: 
   111:     CNumber Number;
00C8A37D 8D 4D EC             lea         ecx,[Number]  
00C8A380 E8 14 97 FF FF       call        CNumber::CNumber (0C83A99h) 

局部对象的析构顺序与构造顺序相反

 

  • 堆对象
  109:     // 局部对象定义调用构造函数
   110: 
   111:     CNumber Number;
00C8A385 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0  
   112:     // 申请堆对象
   113:      CNumber * pNumber = NULL;
00C8A38C C7 45 E0 00 00 00 00 mov         dword ptr [pNumber],0  
   114:      pNumber = new CNumber;
00C8A393 6A 04                push        4  
00C8A395 E8 31 92 FF FF       call        operator new (0C835CBh)  //运算符 new
00C8A39A 83 C4 04             add         esp,4  
00C8A39D 89 85 F0 FE FF FF    mov         dword ptr [ebp-110h],eax  
00C8A3A3 C6 45 FC 01          mov         byte ptr [ebp-4],1  
00C8A3A7 83 BD F0 FE FF FF 00 cmp         dword ptr [ebp-110h],0  //new返回的堆空间地址
00C8A3AE 74 13                je          main+83h (0C8A3C3h)  //为NULL则跳过构造函数
00C8A3B0 8B 8D F0 FE FF FF    mov         ecx,dword ptr [ebp-110h]  
00C8A3B6 E8 DE 96 FF FF       call        CNumber::CNumber (0C83A99h)  //构造函数
00C8A3BB 89 85 A0 FE FF FF    mov         dword ptr [ebp-160h],eax  
00C8A3C1 EB 0A                jmp         main+8Dh (0C8A3CDh)  
00C8A3C3 C7 85 A0 FE FF FF 00 00 00 00 mov         dword ptr [ebp-160h],0  
00C8A3CD 8B 85 A0 FE FF FF    mov         eax,dword ptr [ebp-160h]  
00C8A3D3 89 85 FC FE FF FF    mov         dword ptr [ebp-104h],eax  
00C8A3D9 C6 45 FC 00          mov         byte ptr [ebp-4],0  
00C8A3DD 8B 8D FC FE FF FF    mov         ecx,dword ptr [ebp-104h]  
00C8A3E3 89 4D E0             mov         dword ptr [pNumber],ecx  
   115:      pNumber->m_nNumber = 2;
00C8A3E6 8B 45 E0             mov         eax,dword ptr [pNumber]  
00C8A3E9 C7 00 02 00 00 00    mov         dword ptr [eax],2  
   116:      printf("%d \r\n", pNumber->m_nNumber);
00C8A3EF 8B 45 E0             mov         eax,dword ptr [pNumber]  
00C8A3F2 8B 08                mov         ecx,dword ptr [eax]  
00C8A3F4 51                   push        ecx  
00C8A3F5 68 78 5F D2 00       push        offset string "%d \r\n" (0D25F78h)  
00C8A3FA E8 C6 6F FF FF       call        _printf (0C813C5h)  
00C8A3FF 83 C4 08             add         esp,8  
   117:  
   118:      if (pNumber != NULL)
00C8A402 83 7D E0 00          cmp         dword ptr [pNumber],0  
00C8A406 74 44                je          main+10Ch (0C8A44Ch)  
   119:      {
   120:          delete pNumber;
00C8A408 8B 45 E0             mov         eax,dword ptr [pNumber]  
00C8A40B 89 85 D8 FE FF FF    mov         dword ptr [ebp-128h],eax  
00C8A411 8B 8D D8 FE FF FF    mov         ecx,dword ptr [ebp-128h]  
00C8A417 89 8D E4 FE FF FF    mov         dword ptr [ebp-11Ch],ecx  
00C8A41D 83 BD E4 FE FF FF 00 cmp         dword ptr [ebp-11Ch],0  
00C8A424 74 15                je          main+0FBh (0C8A43Bh)  
00C8A426 6A 01                push        1  
00C8A428 8B 8D E4 FE FF FF    mov         ecx,dword ptr [ebp-11Ch]  
00C8A42E E8 27 80 FF FF       call        CNumber::`scalar deleting destructor' (0C8245Ah)  
00C8A433 89 85 A0 FE FF FF    mov         dword ptr [ebp-160h],eax  
00C8A439 EB 0A                jmp         main+105h (0C8A445h)  
00C8A43B C7 85 A0 FE FF FF 00 00 00 00 mov         dword ptr [ebp-160h],0  
   121:          pNumber = NULL;
00C8A445 C7 45 E0 00 00 00 00 mov         dword ptr [pNumber],0  
   122:      }

释放堆对象数组

   125:     // 释放多个堆对象
   126:     CNumber * pArray = new CNumber[2];
00C8A44C 6A 0C                push        0Ch  
   122:      }
   123: 
   124: 
   125:     // 释放多个堆对象
   126:     CNumber * pArray = new CNumber[2];
00C8A44E E8 0D 75 FF FF       call        operator new[] (0C81960h)  
00C8A453 83 C4 04             add         esp,4  
00C8A456 89 85 C0 FE FF FF    mov         dword ptr [ebp-140h],eax  
00C8A45C C6 45 FC 02          mov         byte ptr [ebp-4],2  
00C8A460 83 BD C0 FE FF FF 00 cmp         dword ptr [ebp-140h],0  
00C8A467 74 3A                je          main+163h (0C8A4A3h)  
00C8A469 8B 85 C0 FE FF FF    mov         eax,dword ptr [ebp-140h]  
00C8A46F C7 00 02 00 00 00    mov         dword ptr [eax],2  
00C8A475 68 9E 2B C8 00       push        offset CNumber::~CNumber (0C82B9Eh)  
00C8A47A 68 99 3A C8 00       push        offset CNumber::CNumber (0C83A99h)  
00C8A47F 6A 02                push        2  
00C8A481 6A 04                push        4  
00C8A483 8B 8D C0 FE FF FF    mov         ecx,dword ptr [ebp-140h]  
00C8A489 83 C1 04             add         ecx,4  
00C8A48C 51                   push        ecx  
00C8A48D E8 11 73 FF FF       call        `eh vector constructor iterator' (0C817A3h)  
00C8A492 8B 95 C0 FE FF FF    mov         edx,dword ptr [ebp-140h]  
00C8A498 83 C2 04             add         edx,4  
00C8A49B 89 95 A0 FE FF FF    mov         dword ptr [ebp-160h],edx  
00C8A4A1 EB 0A                jmp         main+16Dh (0C8A4ADh)  
00C8A4A3 C7 85 A0 FE FF FF 00 00 00 00 mov         dword ptr [ebp-160h],0  
00C8A4AD 8B 85 A0 FE FF FF    mov         eax,dword ptr [ebp-160h]  
00C8A4B3 89 85 CC FE FF FF    mov         dword ptr [ebp-134h],eax  
00C8A4B9 C6 45 FC 00          mov         byte ptr [ebp-4],0  
00C8A4BD 8B 8D CC FE FF FF    mov         ecx,dword ptr [ebp-134h]  
00C8A4C3 89 4D D4             mov         dword ptr [pArray],ecx  
   127:     if (pArray != NULL)
00C8A4C6 83 7D D4 00          cmp         dword ptr [pArray],0  
00C8A4CA 74 44                je          main+1D0h (0C8A510h)  
   128:     {
   129:         delete [] pArray;
00C8A4CC 8B 45 D4             mov         eax,dword ptr [pArray]  
00C8A4CF 89 85 A8 FE FF FF    mov         dword ptr [ebp-158h],eax  
00C8A4D5 8B 8D A8 FE FF FF    mov         ecx,dword ptr [ebp-158h]  
00C8A4DB 89 8D B4 FE FF FF    mov         dword ptr [ebp-14Ch],ecx  
00C8A4E1 83 BD B4 FE FF FF 00 cmp         dword ptr [ebp-14Ch],0  
00C8A4E8 74 15                je          main+1BFh (0C8A4FFh)  
00C8A4EA 6A 03                push        3  
00C8A4EC 8B 8D B4 FE FF FF    mov         ecx,dword ptr [ebp-14Ch]  
00C8A4F2 E8 B7 8A FF FF       call        CNumber::`vector deleting destructor' (0C82FAEh)  
00C8A4F7 89 85 A0 FE FF FF    mov         dword ptr [ebp-160h],eax  
00C8A4FD EB 0A                jmp         main+1C9h (0C8A509h)  
00C8A4FF C7 85 A0 FE FF FF 00 00 00 00 mov         dword ptr [ebp-160h],0  
   130:         pArray = NULL;
00C8A509 C7 45 D4 00 00 00 00 mov         dword ptr [pArray],0  
   131:     }
  • 参数对象
   143:      Show(MyString);
002CA529 51                   push        ecx  //开辟4字节参数对象空间
002CA52A 8B CC                mov         ecx,esp  
002CA52C 89 A5 90 FE FF FF    mov         dword ptr [ebp-170h],esp  
002CA532 8D 45 C8             lea         eax,[MyString]  
002CA535 50                   push        eax  
002CA536 E8 48 74 FF FF       call        CMyString::CMyString (02C1983h) //调用拷贝构造函数,将实参拷贝到开辟的参数对象空间中去。 
002CA53B E8 DB 90 FF FF       call        Show (02C361Bh)  
002CA540 83 C4 04             add         esp,4 

参数对象的析构函数

64: void Show(CMyString MyString){
002CA230 55                   push        ebp  
002CA231 8B EC                mov         ebp,esp  
002CA233 81 EC C0 00 00 00    sub         esp,0C0h  
002CA239 53                   push        ebx  
002CA23A 56                   push        esi  
002CA23B 57                   push        edi  
002CA23C 8D BD 40 FF FF FF    lea         edi,[ebp-0C0h]  
002CA242 B9 30 00 00 00       mov         ecx,30h  
002CA247 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
002CA24C F3 AB                rep stos    dword ptr es:[edi]  
    65:     printf(MyString.m_pString);
002CA24E 8B 45 08             mov         eax,dword ptr [MyString]  
002CA251 50                   push        eax  
002CA252 E8 6E 71 FF FF       call        _printf (02C13C5h)  
002CA257 83 C4 04             add         esp,4  
    66: }
002CA25A 8D 4D 08             lea         ecx,[MyString]  
002CA25D E8 A1 88 FF FF       call        CMyString::~CMyString (02C2B03h)  //在函数内,将进入函数前拷贝构造的参数对象析构。
002CA262 5F                   pop         edi  
002CA263 5E                   pop         esi  
002CA264 5B                   pop         ebx  
002CA265 81 C4 C0 00 00 00    add         esp,0C0h  
002CA26B 3B EC                cmp         ebp,esp  
002CA26D E8 74 8C FF FF       call        __RTC_CheckEsp (02C2EE6h)  
002CA272 8B E5                mov         esp,ebp  
002CA274 5D                   pop         ebp  
002CA275 C3                   ret  
  • 返回对象
  145:     // 返回值为对象类型的拷贝构造使用
   146:     CMyString MyString1 = GetMyString();
002CA543 8D 45 BC             lea         eax,[MyString1]  
002CA546 50                   push        eax  
002CA547 E8 32 97 FF FF       call        GetMyString (02C3C7Eh)  
002CA54C 83 C4 04             add         esp,4  

在返回对象的函数GetMyString内部,会调用拷贝函数,将函数内的局部对象拷贝到进入函数前准备的地址空间中。之后调用析构函数,释放函数内产生的局部对象。

68: // 返回对象
    69: CMyString GetMyString()
    70: {
002C9F40 55                   push        ebp  
002C9F41 8B EC                mov         ebp,esp  
002C9F43 6A FF                push        0FFFFFFFFh  
002C9F45 68 38 2B 36 00       push        362B38h  
002C9F4A 64 A1 00 00 00 00    mov         eax,dword ptr fs:[00000000h]  
002C9F50 50                   push        eax  
002C9F51 81 EC D8 00 00 00    sub         esp,0D8h  
002C9F57 53                   push        ebx  
002C9F58 56                   push        esi  
002C9F59 57                   push        edi  
002C9F5A 8D BD 1C FF FF FF    lea         edi,[ebp-0E4h]  
002C9F60 B9 36 00 00 00       mov         ecx,36h  
002C9F65 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
002C9F6A F3 AB                rep stos    dword ptr es:[edi]  
002C9F6C A1 08 A0 38 00       mov         eax,dword ptr [__security_cookie (038A008h)]  
002C9F71 33 C5                xor         eax,ebp  
002C9F73 50                   push        eax  
002C9F74 8D 45 F4             lea         eax,[ebp-0Ch]  
002C9F77 64 A3 00 00 00 00    mov         dword ptr fs:[00000000h],eax  
002C9F7D C7 85 20 FF FF FF 00 00 00 00 mov         dword ptr [ebp-0E0h],0  
    71:     CMyString MyString;
002C9F87 8D 4D EC             lea         ecx,[MyString]  
002C9F8A E8 74 7C FF FF       call        CMyString::CMyString (02C1C03h)//局部对象,构造函数  
002C9F8F C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0  
    72:     MyString.SetString("World");
002C9F96 68 70 5F 36 00       push        offset string "World" (0365F70h)  
002C9F9B 8D 4D EC             lea         ecx,[MyString]  
002C9F9E E8 44 98 FF FF       call        CMyString::SetString (02C37E7h)  
    73:     return MyString;
002C9FA3 8D 45 EC             lea         eax,[MyString]  
002C9FA6 50                   push        eax  
002C9FA7 8B 4D 08             mov         ecx,dword ptr [ebp+8]  
002C9FAA E8 D4 79 FF FF       call        CMyString::CMyString (02C1983h)//调用拷贝构造函数  
002C9FAF 8B 8D 20 FF FF FF    mov         ecx,dword ptr [ebp-0E0h]  
002C9FB5 83 C9 01             or          ecx,1  
002C9FB8 89 8D 20 FF FF FF    mov         dword ptr [ebp-0E0h],ecx  
002C9FBE C7 45 FC FF FF FF FF mov         dword ptr [ebp-4],0FFFFFFFFh  
002C9FC5 8D 4D EC             lea         ecx,[MyString]  
002C9FC8 E8 36 8B FF FF       call        CMyString::~CMyString (02C2B03h) //函数内的局部对象 析构函数 
002C9FCD 8B 45 08             mov         eax,dword ptr [ebp+8]  
    74: }
  • 全局对象

全局对象的构造函数在启动函数中调用。析构函数在main函数退出时调用。

  • 静态对象

 静态对象构造函数与析构函数调用的时机相同。

 

c++ 反汇编 构造函数和析构函数

上一篇:C++ 反汇编-分析类的实现原理


下一篇:程序员不得不了解的硬核知识大全