关闭

从逆向分析角度看C++的析构函数

发表于:2013-3-15 10:10

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Maxwell_    来源:51Testing软件测试网采编

  有这么一段C++代码:

#include <cstdio>

class CExample {
  int x, y;
 
public:
  CExample(int va, int vb) {
    x = va;
 y = vb;
  }
  CExample(const CExample& C) {
    x = C.x;
 y = C.y;
  }
  ~CExample() {
 printf("~CExample()\n");
  }
 
  void Show () {
    printf("%d, %d\n", x, y);
 return ;
  }
};

void fun(CExample E) {
  printf("In F(CExample)\n");
  return ;
}

int main() {
  CExample A(100, 200);
  CExample B = A;
  B.Show();
  fun(A);
  return 0;
}

  运行结果:

  编译调试的环境是 VC 6.0,注释如下:

  main 函数:

30:   int main() {
00401130   push        ebp
00401131   mov         ebp,esp
00401133   push        0FFh
00401135   push        offset __ehhandler$_main (00413422)
0040113A   mov         eax,fs:[00000000]
00401140   push        eax
00401141   mov         dword ptr fs:[0],esp
00401148   sub         esp,5Ch
0040114B   push        ebx
0040114C   push        esi
0040114D   push        edi
0040114E   lea         edi,[ebp-68h]
00401151   mov         ecx,17h
00401156   mov         eax,0CCCCCCCCh
0040115B   rep stos    dword ptr [edi]    ; 以上代码为建立堆栈,EBP = 1245000
31:     CExample A(100, 200);
0040115D   push        0C8h     ; 将 200 压入堆栈中
00401162   push        64h     ; 将 100 压入堆栈中
00401164   lea         ecx,[ebp-14h]    ; EBP-14h 是 A 的内存地址,占 8 个字节,将该地址保存到 ECX 寄存器中
00401167   call        @ILT+0(CExample::CExample) (00401005) ; 调用构造函数 CExample(int, int)
0040116C   mov         dword ptr [ebp-4],0
32:     CExample B = A;
00401173   lea         eax,[ebp-14h]    ; 将 A 的内存地址保存到 EAX 寄存器中
00401176   push        eax     ; 将 EAX 压入堆栈中
00401177   lea         ecx,[ebp-1Ch]    ; EBP-1Ch 是 B 的内存地址,占 8 个字节,将该地址保存到 ECX 寄存器中
0040117A   call        @ILT+20(CExample::CExample) (00401019) ; 调用拷贝构造函数,将A中的值复制到 B 的内存空间中,   

        ; 细心观察一下栈地址就能明白
0040117F   mov         byte ptr [ebp-4],1
33:     B.Show();
00401183   lea         ecx,[ebp-1Ch]
00401186   call        @ILT+25(CExample::Show) (0040101e)
34:     fun(A);
0040118B   sub         esp,8     ; ESP = 1244884, ESP - 8 = 1244876;ESP-8 是开辟的一块内存,
        ; 在调用fun之前,先调用拷贝构造函数对 A 进行拷贝,拷贝的内容就
        ; 存放在这块内存空间中(一个CExample对象,记为Temp)
0040118E   mov         ecx,esp     ; ECX 寄存器保存 Temp 对象的内存地址
00401190   mov         dword ptr [ebp-20h],esp   ; EBP-20h 这块空间保存 Temp 对象的内存地址
00401193   lea         edx,[ebp-14h]    ; EDX 寄存器保存 A 对象的内存地址
00401196   push        edx     ; ESP = 1244872,将 A 的内存地址压入栈
00401197   call        @ILT+20(CExample::CExample) (00401019) ; ESP = 1244868,函数返回地址压入栈,调用拷贝构造函数
0040119C   mov         dword ptr [ebp-28h],eax   ; ESP = 1244876, EBP - 28h = 1244876,保存 Temp 的内存地址
0040119F   call        @ILT+15(fun) (00401014)   ; ESP = 1244872,函数返回地址压入栈,调用fun函数
004011A4   add         esp,8     ; __cdecl 规则,恢复堆栈段,EBP = 1245000
35:     return 0;
004011A7   mov         dword ptr [ebp-24h],0
004011AE   mov         byte ptr [ebp-4],0
004011B2   lea         ecx,[ebp-1Ch]    ; EBP - 1Ch 是 B 的内存地址,保存到 ECX 中
004011B5   call        @ILT+5(CExample::~CExample) (0040100a) ; 调用析构函数,销毁对象 B
004011BA   mov         dword ptr [ebp-4],0FFFFFFFFh
004011C1   lea         ecx,[ebp-14h]    ; EBP - 14h 是 A 的内存地址,保存到 ECX 中
004011C4   call        @ILT+5(CExample::~CExample) (0040100a) ; 调用析构函数,销毁对象 A
004011C9   mov         eax,dword ptr [ebp-24h]
36:   }

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号