//
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
{
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
}
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++析构的原理了,编译器对调用函数做了个子过程包装,
然后加入析构调用代码.最后返回.
这样看来,如果函数中产生异常,可能会导致析构函数不能正确的调用,从而导致内存泄漏.
根据分析,继续测试.
004114DE call callmyfunc (41125Dh)
0041125D jmp callmyfunc (411520h)
然后直接jmp 到callmyfunc函数的地址.
callmyfunc函数结束的后面,加入了调用析构的代码如下:
00411546 lea ecx,[mytestclass]
00411549 call MyTest::~MyTest (41102Dh)
现在大概知道C++析构的原理了,编译器对调用函数做了个子过程包装,
然后加入析构调用代码.最后返回.
这样看来,如果函数中产生异常,可能会导致析构函数不能正确的调用,从而导致内存泄漏.
根据分析,继续测试.


摘自 天下