反汇编学习之路之构造函数与析构函数(一)

构造函数与析构函数是类的重要组成部分,他们在类中担任着至关重要的工作。够战术常用来完成对象的生成时的初始化工作,而析构函数则常用于在对象销毁时释放对象中的所申请的资源。

当对象生成时,编译器会自动产生调用其类的构造函数的代码,在编码构成中可以分为类中的数据尘烟赋予的初始值,当对象销毁时,编译器同样也会产生调用其析构函数的代码。

构造函数与析构函数都是类中特殊的函数,构造函数可以重载,而析构函数只能有一个,而且析构函数是一个无参析构函数,他们均没有返值,调用构造函数后,返回值为对象的首地址, 也就是我们熟知的this指针。

我们知道,某些情况下,编译器会提供默认的构造函数和析构函数,但是,并不是任何的情况下编译器都提供。问题来了,构造函数出现的时机是在什么时间呢?

构造函数出现的时机

对象在生成时会自动调用构造函数,只要找到了定义对象的地址地方就找到了构造函数的调用时机啦。看似简单,实际情况却相反哦。不同作用域的对象的生命周期也不同,如局部对象,全局对象,静态对象等的生命周期各不相同。而对象作为参数与返回值时,构造函数的出现时机又会不同。

将对象进行分类:不同类型的对象的构造函数被调用的时机会发生变化,但是都会遵循C++语法:定义的同时调用构造函数。那么,只要知道对象的生命周期,便可以推算出构造函数的调用时机。下面先根据生命周期将对象分类,主要分为下面几类:

A,局部对象

B,堆对象

C,参数对象

D,返回对象

E,全局对象

F,静态对象

我们先看看局部对象。

局部对象的构造函数出现的时机比较容易被识别。当对象产生时,便有可能引发构造函数的调用,编译器隐藏了构造函数的调用过程,使编码者无法看到被调用的细节。我们看看下面的分析代码,了解下局部对象的构造函数调用的过程。

class CNumber
{
public:
	CNumber()
	{
		m_number = 1;
	}
private:
	int m_number;
};

///----主函数
int main()
{
	CNumber number;
	system("pause");	///-暂停显示数据

	return 0;
}
在看看对应的构造函数和主函数的汇编代码。

汇编函数的汇编代码:

class CNumber
{
public:
	///---构造函数
	CNumber()
00123620  push        ebp  
00123621  mov         ebp,esp  
00123623  sub         esp,0CCh  
00123629  push        ebx  
0012362A  push        esi  
0012362B  push        edi  
0012362C  push        ecx  
0012362D  lea         edi,[ebp-0CCh]  
00123633  mov         ecx,33h  
00123638  mov         eax,0CCCCCCCCh  
0012363D  rep stos    dword ptr es:[edi]  
0012363F  pop         ecx  
00123640  mov         dword ptr [this],ecx  
	{
		///--变量成员赋值
		m_number = 1;
00123643  mov         eax,dword ptr [this]  
00123646  mov         dword ptr [eax],1  
	}
0012364C  mov         eax,dword ptr [this]  
0012364F  pop         edi  
00123650  pop         esi  
00123651  pop         ebx  
00123652  mov         esp,ebp  
00123654  pop         ebp  
00123655  ret  
再看看主函数 对应的汇编代码:

00123EE0  push        ebp  
00123EE1  mov         ebp,esp  
00123EE3  sub         esp,0D0h  
00123EE9  push        ebx  
00123EEA  push        esi  
00123EEB  push        edi  
00123EEC  lea         edi,[ebp-0D0h]  
00123EF2  mov         ecx,34h  
00123EF7  mov         eax,0CCCCCCCCh  
00123EFC  rep stos    dword ptr es:[edi]  
00123EFE  mov         eax,dword ptr ds:[0012F004h]  
00123F03  xor         eax,ebp  
00123F05  mov         dword ptr [ebp-4],eax  
	CNumber number;
00123F08  lea         ecx,[number]  
00123F0B  call        CNumber::CNumber (01214A6h)  
	system("pause");	///-暂停显示数据
00123F10  mov         esi,esp  
00123F12  push        12CC70h  
00123F17  call        dword ptr ds:[1301E8h]  
00123F1D  add         esp,4  
00123F20  cmp         esi,esp  
00123F22  call        __RTC_CheckEsp (012132Fh)  

	return 0;
00123F27  xor         eax,eax  

当在进入对象的作用域时,编译器产生调用构造函数的代码。由于构造函数属于成员函数,因此在调用的构成中同样需要传递this指针。构造函数调用结束后,会将this指针作为返回值。返回指针便是构造函数的特征之一,结合C++语法,我们就可以总结识别局部对象的构造函数的必要条件(可不是充分条件哦)。

◆该成员函数是这个对象在作用于内调用的第一个成员函数,根据this指针即可以区分每个对象

◆这个函数返回this指针

构造函数必然满足以上两个条件,否则这个函数就不是构造函数。

续...................................................



你可能感兴趣的:(反汇编,构造函数识别)