转自:http://blog.csdn.net/wenrenhua08/article/details/40043811#
在<<逆向C++>>一文中提到 VC6.0 以上的编译器支持一个d1reportAllClassLayout的开关, 可以输出所有对象的内存布局信息, 我自己常用vs2005来开发,所以这里我就以vs2005为例讲怎么设置d1reportAllClassLayout。
右键项目属性(Properties)—》配制属性(Configuration Properties)—》C/C++--》命令行(Command Line)的框里输入/d1reportAllClassLayout,即可看类的对象布局,如下图:(当然也可以使用命令行:cl –d1reportSingleClassLayout[classname] test.cpp)
测试代码:
- class CBase
- {
- public:
- virtual void fun(void) {}
- private:
- int m_valuable;
- };
class CBase
{
public:
virtual void fun(void) {}
private:
int m_valuable;
};
输出结果:
- class CBase size(8):
- +---
- 0 | {vfptr}
- 4 | m_valuable
- +---
- CBase::$vftable@:
- | &CBase_meta
- | 0
- 0 | &CBase::fun
- CBase::fun this adjustor: 0
class CBase size(8):
+---
0 | {vfptr}
4 | m_valuable
+---
CBase::$vftable@:
| &CBase_meta
| 0
0 | &CBase::fun
CBase::fun this adjustor: 0
- CDerived:非virtual继承CBase,持有一个virtual重写方法和一个virtual新方法,一个成员变量
- class CDerived: public CBase
- {
- public:
- void fun(void) { }
- virtual void vfun(void) { }
- public:
- int m_derived;
- };
- 编译后输出结果:
- class CDerived size(12):
- +---
- | +--- (base class CBase)
- 0 | | {vfptr}
- 4 | | m_valuable
- | +---
- 8 | m_derived
- +---
- CDerived::$vftable@:
- | &CDerived_meta
- | 0
- 0 | &CDerived::fun
- 1 | &CDerived::vfun
- CDerived::fun this adjustor: 0
- CDerived::vfun this adjustor: 0
- 其中vftable@CBase的CBase::fun项在这里更新为CDerived::fun,同时增加了一项CDerived::vfun。
- CDerived2:virtual继承CBase,持有一个virtual重写方法和一个virtual新方法,一个成员变量,因此结构为vftable@自身,vbtable@自身,member@自身,以及CBase结构。
- 总结:
- class CDerived2: virtual public CBase
- {
- public:
- void fun(void) { }
- virtual void vfun(void) { }
- public:
- int m_derived;
- };
- 结果输出:
- class CDerived2 size(20):
- +---
- 0 | {vfptr}
- 4 | {vbptr}
- 8 | m_derived
- +---
- +--- (virtual base CBase)
- 12 | {vfptr}
- 16 | m_valuable
- +---
- CDerived2::$vftable@CDerived2@:
- | &CDerived2_meta
- | 0
- 0 | &CDerived2::vfun
- CDerived2::$vbtable@:
- 0 | -4
- 1 | 8 (CDerived2d(CDerived2+4)CBase)
- CDerived2::$vftable@CBase@:
- | -12
- 0 | &CDerived2::fun
- CDerived2::fun this adjustor: 12
- CDerived2::vfun this adjustor: 0
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase 12 4 4 0
- 其中vftable@自身只有一项:CDerived2::vfun(),vbtable@自身只有一项:它virtual继承的父类CBase,而vftable@CBase原来的CBase::fun更新为CDerived2::fun。
- CDerived3:virtual继承CBase,因此结构为vbtable@自身,member@自身,CBase结构
- class CDerived3: virtual public CBase
- {
- public:
- void fun(void) { }
- public:
- int m_derived3;
- };
- 结果输出:
- class CDerived3 size(16):
- +---
- 0 | {vbptr}
- 4 | m_derived3
- +---
- +--- (virtual base CBase)
- 8 | {vfptr}
- 12 | m_valuable
- +---
- CDerived3::$vbtable@:
- 0 | 0
- 1 | 8 (CDerived3d(CDerived3+0)CBase)
- CDerived3::$vftable@:
- | -8
- 0 | &CDerived3::fun
- CDerived3::fun this adjustor: 8
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase 8 0 4 0
- CGDerived:继承CDerived2、CDerived3
- class CGDerived: public CDerived2, public CDerived3
- {
- public:
- void vfun() { }
- virtual void vgfun() { }
- public:
- int m_gd;
- };
- 输出:
- class CGDerived size(32):
- +---
- | +--- (base class CDerived2)
- 0 | | {vfptr}
- 4 | | {vbptr}
- 8 | | m_derived
- | +---
- | +--- (base class CDerived3)
- 12 | | {vbptr}
- 16 | | m_derived3
- | +---
- 20 | m_gd
- +---
- +--- (virtual base CBase)
- 24 | {vfptr}
- 28 | m_valuable
- +---
- CGDerived::$vftable@CDerived2@:
- | &CGDerived_meta
- | 0
- 0 | &CGDerived::vfun
- 1 | &CGDerived::vgfun
- CGDerived::$vbtable@CDerived2@:
- 0 | -4
- 1 | 20 (CGDerivedd(CDerived2+4)CBase)
- CGDerived::$vbtable@CDerived3@:
- 0 | 0
- 1 | 12 (CGDerivedd(CDerived3+0)CBase)
- CGDerived::$vftable@CBase@:
- | -24
- 0 | &thunk: this-=12; goto CDerived2::fun
- CGDerived::vfun this adjustor: 0
- CGDerived::vgfun this adjustor: 0
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase 24 4 4 0
- 因此首先是CDerived2的结构和CDerived3的结构,自己的新virtual方法vgfun则添加在最左父类CDerived2的虚函数表中。然后是自己的成员。最后,CDerived2和CDerived3的父类CBase结构也带入其中。它的fun默认指向CGDerived的最左父类CDerived2::fun。
- CGG:继承CGDerived
- class CGG: public CGDerived
- {
- public:
- int m_kc;
- };
- 输出:
- class CGG size(36):
- +---
- | +--- (base class CGDerived)
- | | +--- (base class CDerived2)
- 0 | | | {vfptr}
- 4 | | | {vbptr}
- 8 | | | m_derived
- | | +---
- | | +--- (base class CDerived3)
- 12 | | | {vbptr}
- 16 | | | m_derived3
- | | +---
- 20 | | m_gd
- | +---
- 24 | m_kc
- +---
- +--- (virtual base CBase)
- 28 | {vfptr}
- 32 | m_valuable
- +---
- CGG::$vftable@CDerived2@:
- | &CGG_meta
- | 0
- 0 | &CGDerived::vfun
- 1 | &CGDerived::vgfun
- CGG::$vbtable@CDerived2@:
- 0 | -4
- 1 | 24 (CGGd(CDerived2+4)CBase)
- CGG::$vbtable@CDerived3@:
- 0 | 0
- 1 | 16 (CGGd(CDerived3+0)CBase)
- CGG::$vftable@CBase@:
- | -28
- 0 | &thunk: this-=16; goto CDerived2::fun
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase 28 4 4 0
- 增加一个变量,基本只是把CGDerived的结构再套一层,最后加上自己的成员变量。vbtable所指向的父类结构依然在最后。
- 空类
- class CBase2
- {
- };
- 输出:
- class CBase2 size(1):
- +---
- +---
- CD2:virtual继承则一定会创建vbtable,用vbptr指针指向,因此size为4
- class CD2: virtual public CBase2
- {
- };
- 输出:
- class CD2 size(4):
- +---
- 0 | {vbptr}
- +---
- +--- (virtual base CBase2)
- +---
- CD2::$vbtable@:
- 0 | 0
- 1 | 4 (CD2d(CD2+0)CBase2)
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase2 4 0 4 0
- CE:非virtual继承CD2和CDerived2,于是按照类的声明顺序,先带入CDerived2的结构,再带入CD2的结构(而不是按继承顺序)
- class CE: public CD2, public CDerived2
- {
- };
- 输出:
- class CE size(24):
- +---
- | +--- (base class CDerived2)
- 0 | | {vfptr}
- 4 | | {vbptr}
- 8 | | m_derived
- | +---
- | +--- (base class CD2)
- 12 | | {vbptr}
- | +---
- +---
- +--- (virtual base CBase2)
- +---
- +--- (virtual base CBase)
- 16 | {vfptr}
- 20 | m_valuable
- +---
- CE::$vftable@CDerived2@:
- | &CE_meta
- | 0
- 0 | &CDerived2::vfun
- CE::$vbtable@CD2@:
- 0 | 0
- 1 | 4 (CEd(CD2+0)CBase2)
- 2 | 4 (CEd(CE+12)CBase)
- CE::$vbtable@CDerived2@:
- 0 | -4
- 1 | 12 (CEd(CDerived2+4)CBase)
- CE::$vftable@CBase@:
- | -16
- 0 | &thunk: this-=4; goto CDerived2::fun
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase2 16 12 4 0
- CBase 16 12 8 0
- CF:virtual继承CBase和CBase2,vbtable此时的项便有两个,此时按照继承的顺序,而不是按照类的声明顺序
- class CF: virtual public CBase2, virtual public CBase
- {
- };
- 输出:
- class CF size(12):
- +---
- 0 | {vbptr}
- +---
- +--- (virtual base CBase2)
- +---
- +--- (virtual base CBase)
- 4 | {vfptr}
- 8 | m_valuable
- +---
- CF::$vbtable@:
- 0 | 0
- 1 | 4 (CFd(CF+0)CBase2)
- 2 | 4 (CFd(CF+0)CBase)
- CF::$vftable@:
- | -4
- 0 | &CBase::fun
- vbi: class offset o.vbptr o.vbte fVtorDisp
- CBase2 4 0 4 0
- CBase 4 0 8 0
CDerived:非virtual继承CBase,持有一个virtual重写方法和一个virtual新方法,一个成员变量
class CDerived: public CBase
{
public:
void fun(void) { }
virtual void vfun(void) { }
public:
int m_derived;
};
编译后输出结果:
class CDerived size(12):
+---
| +--- (base class CBase)
0 | | {vfptr}
4 | | m_valuable
| +---
8 | m_derived
+---
CDerived::$vftable@:
| &CDerived_meta
| 0
0 | &CDerived::fun
1 | &CDerived::vfun
CDerived::fun this adjustor: 0
CDerived::vfun this adjustor: 0
其中vftable@CBase的CBase::fun项在这里更新为CDerived::fun,同时增加了一项CDerived::vfun。
CDerived2:virtual继承CBase,持有一个virtual重写方法和一个virtual新方法,一个成员变量,因此结构为vftable@自身,vbtable@自身,member@自身,以及CBase结构。
总结:
class CDerived2: virtual public CBase
{
public:
void fun(void) { }
virtual void vfun(void) { }
public:
int m_derived;
};
结果输出:
class CDerived2 size(20):
+---
0 | {vfptr}
4 | {vbptr}
8 | m_derived
+---
+--- (virtual base CBase)
12 | {vfptr}
16 | m_valuable
+---
CDerived2::$vftable@CDerived2@:
| &CDerived2_meta
| 0
0 | &CDerived2::vfun
CDerived2::$vbtable@:
0 | -4
1 | 8 (CDerived2d(CDerived2+4)CBase)
CDerived2::$vftable@CBase@:
| -12
0 | &CDerived2::fun
CDerived2::fun this adjustor: 12
CDerived2::vfun this adjustor: 0
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase 12 4 4 0
其中vftable@自身只有一项:CDerived2::vfun(),vbtable@自身只有一项:它virtual继承的父类CBase,而vftable@CBase原来的CBase::fun更新为CDerived2::fun。
CDerived3:virtual继承CBase,因此结构为vbtable@自身,member@自身,CBase结构
class CDerived3: virtual public CBase
{
public:
void fun(void) { }
public:
int m_derived3;
};
结果输出:
class CDerived3 size(16):
+---
0 | {vbptr}
4 | m_derived3
+---
+--- (virtual base CBase)
8 | {vfptr}
12 | m_valuable
+---
CDerived3::$vbtable@:
0 | 0
1 | 8 (CDerived3d(CDerived3+0)CBase)
CDerived3::$vftable@:
| -8
0 | &CDerived3::fun
CDerived3::fun this adjustor: 8
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase 8 0 4 0
CGDerived:继承CDerived2、CDerived3
class CGDerived: public CDerived2, public CDerived3
{
public:
void vfun() { }
virtual void vgfun() { }
public:
int m_gd;
};
输出:
class CGDerived size(32):
+---
| +--- (base class CDerived2)
0 | | {vfptr}
4 | | {vbptr}
8 | | m_derived
| +---
| +--- (base class CDerived3)
12 | | {vbptr}
16 | | m_derived3
| +---
20 | m_gd
+---
+--- (virtual base CBase)
24 | {vfptr}
28 | m_valuable
+---
CGDerived::$vftable@CDerived2@:
| &CGDerived_meta
| 0
0 | &CGDerived::vfun
1 | &CGDerived::vgfun
CGDerived::$vbtable@CDerived2@:
0 | -4
1 | 20 (CGDerivedd(CDerived2+4)CBase)
CGDerived::$vbtable@CDerived3@:
0 | 0
1 | 12 (CGDerivedd(CDerived3+0)CBase)
CGDerived::$vftable@CBase@:
| -24
0 | &thunk: this-=12; goto CDerived2::fun
CGDerived::vfun this adjustor: 0
CGDerived::vgfun this adjustor: 0
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase 24 4 4 0
因此首先是CDerived2的结构和CDerived3的结构,自己的新virtual方法vgfun则添加在最左父类CDerived2的虚函数表中。然后是自己的成员。最后,CDerived2和CDerived3的父类CBase结构也带入其中。它的fun默认指向CGDerived的最左父类CDerived2::fun。
CGG:继承CGDerived
class CGG: public CGDerived
{
public:
int m_kc;
};
输出:
class CGG size(36):
+---
| +--- (base class CGDerived)
| | +--- (base class CDerived2)
0 | | | {vfptr}
4 | | | {vbptr}
8 | | | m_derived
| | +---
| | +--- (base class CDerived3)
12 | | | {vbptr}
16 | | | m_derived3
| | +---
20 | | m_gd
| +---
24 | m_kc
+---
+--- (virtual base CBase)
28 | {vfptr}
32 | m_valuable
+---
CGG::$vftable@CDerived2@:
| &CGG_meta
| 0
0 | &CGDerived::vfun
1 | &CGDerived::vgfun
CGG::$vbtable@CDerived2@:
0 | -4
1 | 24 (CGGd(CDerived2+4)CBase)
CGG::$vbtable@CDerived3@:
0 | 0
1 | 16 (CGGd(CDerived3+0)CBase)
CGG::$vftable@CBase@:
| -28
0 | &thunk: this-=16; goto CDerived2::fun
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase 28 4 4 0
增加一个变量,基本只是把CGDerived的结构再套一层,最后加上自己的成员变量。vbtable所指向的父类结构依然在最后。
空类
class CBase2
{
};
输出:
class CBase2 size(1):
+---
+---
CD2:virtual继承则一定会创建vbtable,用vbptr指针指向,因此size为4
class CD2: virtual public CBase2
{
};
输出:
class CD2 size(4):
+---
0 | {vbptr}
+---
+--- (virtual base CBase2)
+---
CD2::$vbtable@:
0 | 0
1 | 4 (CD2d(CD2+0)CBase2)
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase2 4 0 4 0
CE:非virtual继承CD2和CDerived2,于是按照类的声明顺序,先带入CDerived2的结构,再带入CD2的结构(而不是按继承顺序)
class CE: public CD2, public CDerived2
{
};
输出:
class CE size(24):
+---
| +--- (base class CDerived2)
0 | | {vfptr}
4 | | {vbptr}
8 | | m_derived
| +---
| +--- (base class CD2)
12 | | {vbptr}
| +---
+---
+--- (virtual base CBase2)
+---
+--- (virtual base CBase)
16 | {vfptr}
20 | m_valuable
+---
CE::$vftable@CDerived2@:
| &CE_meta
| 0
0 | &CDerived2::vfun
CE::$vbtable@CD2@:
0 | 0
1 | 4 (CEd(CD2+0)CBase2)
2 | 4 (CEd(CE+12)CBase)
CE::$vbtable@CDerived2@:
0 | -4
1 | 12 (CEd(CDerived2+4)CBase)
CE::$vftable@CBase@:
| -16
0 | &thunk: this-=4; goto CDerived2::fun
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase2 16 12 4 0
CBase 16 12 8 0
CF:virtual继承CBase和CBase2,vbtable此时的项便有两个,此时按照继承的顺序,而不是按照类的声明顺序
class CF: virtual public CBase2, virtual public CBase
{
};
输出:
class CF size(12):
+---
0 | {vbptr}
+---
+--- (virtual base CBase2)
+---
+--- (virtual base CBase)
4 | {vfptr}
8 | m_valuable
+---
CF::$vbtable@:
0 | 0
1 | 4 (CFd(CF+0)CBase2)
2 | 4 (CFd(CF+0)CBase)
CF::$vftable@:
| -4
0 | &CBase::fun
vbi: class offset o.vbptr o.vbte fVtorDisp
CBase2 4 0 4 0
CBase 4 0 8 0
总结:
继承方式:非virtual继承:导入各个父类的结构(按照父类声明的顺序,从上到下),自身member在最后
重写virtual方法:更新该方法最早定义的类的vftable
新的virtual方法:在最左父类的vftable增加
继承方式:有virtual继承:在自身member后增加virtual父类的结构(按照子类继承的顺序从左到右),同时在最前面增加vbtable(如果没有的话),增加一项指向父类结构
重写virtual方法:更新该方法的最早定义的类的vftable
新的virtual方法:在自身最前面增加vftable(如果没有的话),在自己的vftable增加
- #ifndef TEST_CBASE_H
- #define TEST_CBASE_H
- class CBase
- {
- public:
- CBase();
- explicit CBase(int valuabel);
- ~CBase();
- virtual void fun(void) {}
- private:
- int m_valuable;
- };
- class CDerived: public CBase
- {
- public:
- void fun(void) { }
- virtual void vfun(void) { }
- public:
- int m_derived;
- };
- class CDerived2: virtual public CBase
- {
- public:
- void fun(void) { }
- virtual void vfun(void) { }
- public:
- int m_derived;
- };
- class CDerived3: virtual public CBase
- {
- public:
- void fun(void) { }
- public:
- int m_derived3;
- };
- class CGDerived: public CDerived2, public CDerived3
- {
- public:
- void vfun() { }
- virtual void vgfun() { }
- public:
- int m_gd;
- };
- class CGG: public CGDerived
- {
- public:
- int m_kc;
- };
- class CBase2
- {
- };
- class CD2: virtual public CBase2
- {
- };
- class CE: public CD2, public CDerived2
- {
- };
- class CF: virtual public CBase2, virtual public CBase
- {
- };
- #endif//TEST_CBASE_H
#ifndef TEST_CBASE_H
#define TEST_CBASE_H
class CBase
{
public:
CBase();
explicit CBase(int valuabel);
~CBase();
virtual void fun(void) {}
private:
int m_valuable;
};
class CDerived: public CBase
{
public:
void fun(void) { }
virtual void vfun(void) { }
public:
int m_derived;
};
class CDerived2: virtual public CBase
{
public:
void fun(void) { }
virtual void vfun(void) { }
public:
int m_derived;
};
class CDerived3: virtual public CBase
{
public:
void fun(void) { }
public:
int m_derived3;
};
class CGDerived: public CDerived2, public CDerived3
{
public:
void vfun() { }
virtual void vgfun() { }
public:
int m_gd;
};
class CGG: public CGDerived
{
public:
int m_kc;
};
class CBase2
{
};
class CD2: virtual public CBase2
{
};
class CE: public CD2, public CDerived2
{
};
class CF: virtual public CBase2, virtual public CBase
{
};
#endif//TEST_CBASE_H