vs2008下C++对象内存布局(1)

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

 

本文适用于

Xp sp3

Vs2008

 

欢迎转载,但请保留作者信息

 

近日,因为调试cygwin.dll出了点状况,与C++对象的内存布局有关,故此决定先看看vs2008C++对象内存的管理。

1.1    最简单的类

写一小段简单代码:

class CTest

{

public:

     int var_a;

     int var_b;

     int var_c;

 

public:

     void fun1()

     {

         var_a = 10;

     }

     void fun2()

     {

         var_b = 20;

     }

};

 

CTest a, *p;

 

int _tmain(int argc, _TCHAR* argv[])

{

     a.var_a = 1;

     a.var_b = 2;

     a.var_c = 3;

 

     p = &a;

     p->fun1();

     p->fun2();

     return 0;

}

为了更直观地观察编译器的行为,把ap做为全局变量。

1.1.1   赋值语句的行为

先观察赋值语句的行为:

     a.var_a = 1;

004113CE C7 05 C0 74 41 00 01 00 00 00 mov         dword ptr [a (4174C0h)],1

     a.var_b = 2;

004113D8 C7 05 C4 74 41 00 02 00 00 00 mov         dword ptr [a+4 (4174C4h)],2

     a.var_c = 3;

004113E2 C7 05 C8 74 41 00 03 00 00 00 mov         dword ptr [a+8 (4174C8h)],3

再观察赋值结束后p指向的内存区域:

0x004174C0  01 00 00 00 02 00 00 00 03 00 00 00 00 00 00  ...............

显然,这个时候p指向CTest::var_a,也就是说vs2008并没有在类中插入多余的内容。CTest的大小为var_a, var_b, var_c的大小之和,即12个字节。

1.1.2   函数调用的行为

再观察一下函数调用的行为:

     p->fun1();

004113F6 8B 0D BC 74 41 00 mov         ecx,dword ptr [p (4174BCh)]

004113FC E8 53 FD FF FF   call        CTest::fun1 (411154h)

这段代码可以说明CTest::fun1的调用和其它的C代码并没有什么不同,一个函数而已。看看call把我们带到哪里:

00411118 E9 83 03 00 00   jmp         CTest::fun2 (4114A0h)

0041111D E9 6E 15 00 00   jmp         __CxxUnhandledExceptionFilter (412690h)

00411122 E9 E9 15 00 00   jmp         __CxxSetUnhandledExceptionFilter (412710h)

00411127 E9 64 24 00 00   jmp         QueryPerformanceCounter (413590h)

0041112C E9 9F 16 00 00   jmp         _wsetargv (4127D0h)

00411131 E9 0A 17 00 00   jmp         __p__commode (412840h)

00411136 E9 89 22 00 00   jmp         _unlock (4133C4h)

0041113B E9 62 24 00 00   jmp         GetCurrentProcessId (4135A2h)

00411140 E9 9B 04 00 00   jmp         _RTC_CheckStackVars2 (4115E0h)

00411145 E9 80 18 00 00   jmp         __set_app_type (4129CAh)

0041114A E9 A1 03 00 00   jmp         _RTC_CheckEsp (4114F0h)

0041114F E9 8C 16 00 00   jmp         _RTC_Initialize (4127E0h)

00411154 E9 07 03 00 00   jmp         CTest::fun1 (411460h)

一个神秘的地方,只是func1func2为什么要离得这么远呢?莫非有什么特殊的考虑?暂且不管它,在jmp的带领下,看到了func1的代码:

     void fun1()

     {

00411460 55               push        ebp 

00411461 8B EC            mov         ebp,esp

00411463 81 EC CC 00 00 00 sub         esp,0CCh

00411469 53               push        ebx 

0041146A 56               push        esi 

0041146B 57               push        edi 

0041146C 51               push        ecx 

0041146D 8D BD 34 FF FF FF lea         edi,[ebp-0CCh]

00411473 B9 33 00 00 00   mov         ecx,33h

00411478 B8 CC CC CC CC   mov         eax,0CCCCCCCCh

0041147D F3 AB            rep stos    dword ptr es:[edi]

0041147F 59               pop         ecx  

00411480 89 4D F8         mov         dword ptr [ebp-8],ecx

         var_a = 10;

00411483 8B 45 F8         mov         eax,dword ptr [this]

00411486 C7 00 0A 00 00 00 mov         dword ptr [eax],0Ah

     }

0041148C 5F               pop         edi 

0041148D 5E               pop         esi 

0041148E 5B               pop         ebx 

0041148F 8B E5            mov         esp,ebp

00411491 5D               pop         ebp 

00411492 C3               ret             

传说中的对象应该有一个this指针的,怎么传递过来的?

在调用fun1之前,将p的值赋给了ecx,在fun1里面,其它寄存器都是函数开始就入栈,函数退出时再出栈,唯独ecx是个例外,想来vs就是通过ECX来传递this指针的值。

1.1.3   p指向自定义的缓冲区

由于在此种简单情况下,vs2008并没有添加额外的空间,想来把p指向自己定义的数组再调用其成员函数应该也可以工作得很好,试试下面的代码:

     int buf[3] = {4, 5, 6};

     p = (CTest*)buf;

     p->fun1();

经过此调用,buf[0]的值果然变成了10

 

 

 

 

 

 

你可能感兴趣的:(C++,c,工作,Class,编译器,fun)