天下

记录修行的印记

C++构造函数与析构函数


//a.h代码:
#pragma once
#include 
<iostream>
using namespace std;
void test();

#include "a.h"
//a.cpp代码:
class MyTest
{
public:
    MyTest(){
        cout 
<< "MyTest()" << endl;
    }
    
~MyTest(){
        cout 
<< "~MyTest()" << endl;
    }
};
void test()
{
    MyTest test;
}

//main.cpp
#include <iostream>
#include 
"a.h"
int main() 
{
    test();
    
int a=5;
    
int b=6;
    
return 0;
}

int main()
{
004114C0  push        ebp  
004114C1  mov         ebp,esp
004114C3  sub         esp,0D8h
004114C9  push        ebx  
004114CA  push        esi  
004114CB  push        edi  
004114CC  lea         edi,[ebp-0D8h]
004114D2  mov         ecx,36h
004114D7  mov         eax,0CCCCCCCCh
004114DC  rep stos    dword ptr es:[edi]
    callmyfunc();
004114DE  call        callmyfunc (41125Dh)
    int a=5;
004114E3  mov         dword ptr [a],5
    int b=6;
004114EA  mov         dword ptr [b],6
    return 0;
004114F1  xor         eax,eax
}

0041125D  jmp         callmyfunc (411520h)

void callmyfunc()
{
00411520  push        ebp  
00411521  mov         ebp,esp
00411523  sub         esp,0CCh
00411529  push        ebx  
0041152A  push        esi  
0041152B  push        edi  
0041152C  lea         edi,[ebp-0CCh]
00411532  mov         ecx,33h
00411537  mov         eax,0CCCCCCCCh
0041153C  rep stos    dword ptr es:[edi]
    MyTest mytestclass;
0041153E  lea         ecx,[mytestclass]
00411541  call        MyTest::MyTest (4111C7h)
}
00411546  lea         ecx,[mytestclass]
00411549  call        MyTest::~MyTest (41102Dh)
0041154E  push        edx  
0041154F  mov         ecx,ebp
00411551  push        eax  
00411552  lea         edx,[ (411574h)]
00411558  call        @ILT+170(@_RTC_CheckStackVars@8) (4110AFh)
0041155D  pop         eax  
0041155E  pop         edx  
0041155F  pop         edi  
00411560  pop         esi  
00411561  pop         ebx  
00411562  add         esp,0CCh
00411568  cmp         ebp,esp
0041156A  call        @ILT+415(__RTC_CheckEsp) (4111A4h)
0041156F  mov         esp,ebp
00411571  pop         ebp  
00411572  ret




call 指令
CPU执行call指令,进行两步操作:
1)将当前的 IP 或 CS和IP 压入栈中;
2)转移。

call 指令在实现转移之前, 要将返回地址存入堆栈的, 以便子程可以通过 ret 指令返回到 CALL 指令下面的指令接着运行;
jmp 就没用这些事儿, 直接过去就过去了, 以后的执行流程全由那里的说了算. 当然了, 一些特殊的执行流程控制技巧除外.




大概的意思,汇编我也不怎么懂.
004114DE  call        callmyfunc (41125Dh)
0041125D  jmp         callmyfunc (411520h)
然后直接jmp 到callmyfunc函数的地址.
callmyfunc函数结束的后面,加入了调用析构的代码如下:
00411546  lea         ecx,[mytestclass]
00411549  call        MyTest::~MyTest (41102Dh)

现在大概知道C++析构的原理了,编译器对调用函数做了个子过程包装,
然后加入析构调用代码.最后返回.

这样看来,如果函数中产生异常,可能会导致析构函数不能正确的调用,从而导致内存泄漏.

根据分析,继续测试.







C++标准规定,本地对象的析构函数的调用顺序与他们的构造顺序相反。
C++标准规定,本地对象的析构函数的调用顺序与他们的构造顺序相反。
C++标准规定,本地对象的析构函数的调用顺序与他们的构造顺序相反。
C++标准规定,本地对象的析构函数的调用顺序与他们的构造顺序相反。
//C++标准规定,本地对象的析构函数的调用顺序与他们的构造顺序相反。

void callMyTest()
{
    MyTestA MyTestAObj;
    MyTestB MyTestBObj;
}

int main() 
{
004121B0  push        ebp  
004121B1  mov         ebp,esp 
004121B3  sub         esp,0D8h 
004121B9  push        ebx  
004121BA  push        esi  
004121BB  push        edi  
004121BC  lea         edi,[ebp
-0D8h] 
004121C2  mov         ecx,36h 
004121C7  mov         eax,0CCCCCCCCh 
004121CC  rep stos    dword ptr es:[edi] 
    callMyTest();
004121CE  call        callMyTest (411159h) 
    
int a=5;
004121D3  mov         dword ptr [a],
5 
    
int b=6;
004121DA  mov         dword ptr [b],
6 
    
return 0;
004121E1  xor         eax,eax 
}

00411159  jmp         callMyTest (411540h) 



void callMyTest()
{
00411540  push        ebp  
00411541  mov         ebp,esp 
00411543  push        0FFFFFFFFh 
00411545  push        offset __ehhandler$?callMyTest@@YAXXZ (4155E8h) 
0041154A  mov         eax,dword ptr fs:[00000000h] 
00411550  push        eax  
00411551  sub         esp,0D8h 
00411557  push        ebx  
00411558  push        esi  
00411559  push        edi  
0041155A  lea         edi,[ebp
-0E4h] 
00411560  mov         ecx,36h 
00411565  mov         eax,0CCCCCCCCh 
0041156A  rep stos    dword ptr es:[edi] 
0041156C  mov         eax,dword ptr [___security_cookie (41B044h)] 
00411571  xor         eax,ebp 
00411573  push        eax  
00411574  lea         eax,[ebp-0Ch] 
00411577  mov         dword ptr fs:[00000000h],eax 
    MyTestA MyTestAObj;
0041157D  lea         ecx,[ebp
-11h] 
00411580  call        MyTestA::MyTestA (4110FAh) 
00411585  mov         dword ptr [ebp-4],0 
    MyTestB MyTestBObj;
0041158C  lea         ecx,[ebp
-1Dh] 
0041158F  call        MyTestB::MyTestB (41103Ch) 
}
00411594  lea         ecx,[ebp-1Dh] 
00411597  call        MyTestB::~MyTestB (41114Fh) 
0041159C  mov         dword ptr [ebp
-4],0FFFFFFFFh 
004115A3  lea         ecx,[ebp
-11h] 
004115A6  call        MyTestA::
~MyTestA (411226h) 
004115AB  push        edx  
004115AC  mov         ecx,ebp 
004115AE  push        eax  
004115AF  lea         edx,[ (4115DCh)] 
004115B5  call        @ILT
+185(@_RTC_CheckStackVars@8) (4110BEh) 
004115BA  pop         eax  
004115BB  pop         edx  
004115BC  mov         ecx,dword ptr [ebp
-0Ch] 
004115BF  mov         dword ptr fs:[
0],ecx 
004115C6  pop         ecx  
004115C7  pop         edi  
004115C8  pop         esi  
004115C9  pop         ebx  
004115CA  add         esp,0E4h 
004115D0  cmp         ebp,esp 
004115D2  call        @ILT
+465(__RTC_CheckEsp) (4111D6h) 
004115D7  mov         esp,ebp 
004115D9  pop         ebp  
004115DA  ret  






posted on 2011-10-22 10:29 天下 阅读(1520) 评论(0)  编辑 收藏 引用 所属分类: C/C++Win32


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年10月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

常用链接

留言簿(4)

随笔分类(377)

随笔档案(327)

链接

最新随笔

搜索

最新评论