C++构造函数与析构函数
              	来源:岁月联盟
                
                时间:2011-10-27
              
          
	//a.h代码:
#pragma once
#include <iostream>
using namespace std;
void test();
      
        
      
    	
            
                  
                    
                
            
        
        
            
                  
                    
                
            
    
    
  
  
  
    
  
#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;
}
    //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;
}
            
      
      
    #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++析构的原理了,编译器对调用函数做了个子过程包装,
然后加入析构调用代码.最后返回.
	
这样看来,如果函数中产生异常,可能会导致析构函数不能正确的调用,从而导致内存泄漏.
	
根据分析,继续测试.
              
             
         
         {
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++中map用法
            
        最近更新
随机推荐
- 以服务为诱饵 今天你的MSN被钓了么?(
 - 手机误删照片怎么恢复?第二招可以说
 - MS09-034:Internet Explorer 的累积
 - “质量革命”背后:瓜子二手车的底层
 - 苹果手机被挤出中国市场前五名 因欠缺
 - 暗流涌动的产业互联网,阿里、腾讯之
 - 或许iPhone 5完美越狱真的要来了
 - PHP MSQL_Connect 函数远程存在栈溢出
 - Windows版iTunes存缺陷 安全运行任意
 - 2014世界杯域名战 .WANG重拾中国信心
 - 微软发布新IE安全漏洞公告
 - 警惕网上黑帮成为诱发青少年犯罪温床
 - Virtual PC和Virtual Server虚拟机的
 - 互联网将如何颠覆传统产业
 - 微软IE浏览器曝严重漏洞 可远程控制电
 - 版权战,爱奇艺要起诉优酷盗版侵权
 - 梭子鱼负载均衡机在中间件系统中的应
 - Btrfs文件系统被发现易受基于哈希碰撞
 - 刚刚"而立"的在线教育怎样才能做到"不
 - 特大黑客案破获 一公司网站遭攻击瘫痪
 




