C++ 内存分析(4)

菱形虚继承
    菱形虚继承是多继承和虚继承的复合
    验证:顺序
        派生类VPtr虚表;
        派生类VBPtr表;        
        派生类成员;
        公共基类VPtr;
        公共基类成员;
        首个基类VPtr虚表; (继承列表顺序)
        首个基类VBPtr表;
        首个基类成员;
        第二个基类VPtr虚表;
        第二个基类VBPtr虚表
        第二个基类成员;
        …    

环境:VS2017

*.h

//基类3
class FBase3 : virtual public FBase
{
public:
	char m_cBase3Memeber;
public:
	//构造
	FBase3() {}
	//虚析构
	virtual ~FBase3() {}
public:
	virtual void Base3VirtualFun1() { std::cout << "FBase3::BaseVirtualFun1()\n"; }
	virtual void Base3VirtualFun2() { std::cout << "FBase3::BaseVirtualFun2()\n"; }
};
//基类4
class FBase4 : virtual public FBase
{
public:
	char m_cBase4Memeber;

public:
	//构造
	FBase4() {}
	//虚析构
	virtual ~FBase4() {}
public:
	virtual void Base4VirtualFun1() { std::cout << "FBase4::BaseVirtualFun1()\n"; }
	virtual void Base4VirtualFun2() { std::cout << "FBase4::BaseVirtualFun2()\n"; }
};

//菱形虚继承
class FDiamondInheritanceDerive : virtual public FBase4, virtual public FBase3
{
public:
	//构造
	FDiamondInheritanceDerive() {}
	//虚析构
	virtual ~FDiamondInheritanceDerive() {}
public:
	//重写 基类虚函数
	virtual void BaseVirtualFun1() override { std::cout << "FDiamondInheritanceDerive::BaseVirtualFun1()\n"; }
	//重写 基类3虚函数
	virtual void Base3VirtualFun1() override { std::cout << "FDiamondInheritanceDerive::Base3VirtualFun1()\n"; }
	//新增虚函数
	virtual void VirtualFun3() { std::cout << "FDiamondInheritanceDerive::VirtualFun3()\n"; }

public:
	//成员
	char m_cDiamondInheritanceDeriveMemeber;
};

/*	配置属性-》C++ -》命令行: /d1 reportAllClassLayout

//--------------------------------------------x86--------------------------------------------
1>class FDiamondInheritanceDerive	size(40):
1>	+---
1> 0	| {vfptr}
1> 4	| {vbptr}
1> 8	| m_cDiamondInheritanceDeriveMemeber
1>	+---

1>FDiamondInheritanceDerive::$vftable@:
1>	| &FDiamondInheritanceDerive_meta
1>	|  0
1> 0	| &FDiamondInheritanceDerive::VirtualFun3
1>
1>FDiamondInheritanceDerive::$vbtable@FDiamondInheritanceDerive@:
1> 0	| -4
1> 1	| 9 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+4)FBase)
1> 2	| 14 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+4)FBase4)
1> 3	| 27 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+4)FBase3)
1>
1>FDiamondInheritanceDerive::$vftable@FBase@:
1>	| -13
1> 0	| &(vtordisp) FDiamondInheritanceDerive::BaseVirtualFun1
1> 1	| &FBase::BaseVirtualFun2
1>
1>FDiamondInheritanceDerive::$vftable@FBase4@:
1>	| -18
1> 0	| &FDiamondInheritanceDerive::{dtor}
1> 1	| &FBase4::Base4VirtualFun1
1> 2	| &FBase4::Base4VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase4@:
1> 0	| -4
1> 1	| -9 (FDiamondInheritanceDerived(FBase4+4)FBase)
1>
1>FDiamondInheritanceDerive::$vftable@FBase3@:
1>	| -31
1> 0	| &(vtordisp) thunk: this-=13; goto FDiamondInheritanceDerive::{dtor}
1> 1	| &(vtordisp) FDiamondInheritanceDerive::Base3VirtualFun1
1> 2	| &FBase3::Base3VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase3@:
1> 0	| -4
1> 1	| -22 (FDiamondInheritanceDerived(FBase3+4)FBase)
1>

//--------------------------------------------x64--------------------------------------------
1>class FDiamondInheritanceDerive	size(68):
1>	+---
1> 0	| {vfptr}
1> 8	| {vbptr}
1>16	| m_cDiamondInheritanceDeriveMemeber
1>	+---
1>17	| (vtordisp for vbase FBase)
1>	+--- (virtual base FBase)
1>21	| {vfptr}
1>29	| m_cBaseMemeber
1>	+---
1>	+--- (virtual base FBase4)
1>30	| {vfptr}
1>38	| {vbptr}
1>46	| m_cBase4Memeber
1>	+---
1>47	| (vtordisp for vbase FBase3)
1>	+--- (virtual base FBase3)
1>51	| {vfptr}
1>59	| {vbptr}
1>67	| m_cBase3Memeber
1>	+---
1>
1>FDiamondInheritanceDerive::$vftable@:
1>	| &FDiamondInheritanceDerive_meta
1>	|  0
1> 0	| &FDiamondInheritanceDerive::VirtualFun3
1>
1>FDiamondInheritanceDerive::$vbtable@FDiamondInheritanceDerive@:
1> 0	| -8
1> 1	| 13 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+8)FBase)
1> 2	| 22 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+8)FBase4)
1> 3	| 43 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+8)FBase3)
1>
1>FDiamondInheritanceDerive::$vftable@FBase@:
1>	| -21
1> 0	| &(vtordisp) FDiamondInheritanceDerive::BaseVirtualFun1
1> 1	| &FBase::BaseVirtualFun2
1>
1>FDiamondInheritanceDerive::$vftable@FBase4@:
1>	| -30
1> 0	| &FDiamondInheritanceDerive::{dtor}
1> 1	| &FBase4::Base4VirtualFun1
1> 2	| &FBase4::Base4VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase4@:
1> 0	| -8
1> 1	| -17 (FDiamondInheritanceDerived(FBase4+8)FBase)
1>
1>FDiamondInheritanceDerive::$vftable@FBase3@:
1>	| -51
1> 0	| &(vtordisp) thunk: this-=21; goto FDiamondInheritanceDerive::{dtor}
1> 1	| &(vtordisp) FDiamondInheritanceDerive::Base3VirtualFun1
1> 2	| &FBase3::Base3VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase3@:
1> 0	| -8
1> 1	| -38 (FDiamondInheritanceDerived(FBase3+8)FBase)
1>




vtordisp
	vtordisp是一个C++编译器的实现细节,主要用于解决类的多继承中虚函数表指针的偏移问题。在C++多继承中,每个基类都有自己的虚函数表指针,但是在派生类中只能有一个虚函数表指针,所以需要通过vtordisp来计算每个基类的虚函数表指针在派生类中的偏移量,从而实现正确的调用。

vtordisp的具体实现方式因编译器而异,例如在Visual C++中使用了虚基类表和偏移量表来计算偏移量。虚基类表是一个全局表,用于存储虚基类的偏移量和虚函数表指针。偏移量表则是每个类的成员变量之前添加的一段空间,在其中存储了各个基类在当前类中的偏移量,包括虚基类和非虚基类。通过这些表的信息,编译器可以在派生类中正确地计算出每个基类的虚函数表指针在派生类中的偏移量。

需要注意的是,vtordisp只在多继承的情况下才会使用,对于单继承的类,虚函数表指针不需要进行偏移。同时,由于vtordisp是编译器的实现细节,因此不建议在代码中直接使用vtordisp。
*/

*.cpp

/*
菱形虚继承
	菱形虚继承是多继承和虚继承的复合
	验证:顺序	
*/
void DiamondInheritanceDerive_Test()
{
	std::cout << std::endl << std::endl << "------------------------------------DiamondInheritanceDerive_Test-------------------------Start" << std::endl;
	FDiamondInheritanceDerive DiamondInheritanceDerive;
	DiamondInheritanceDerive.m_cBaseMemeber = 10;
	DiamondInheritanceDerive.m_cBase3Memeber = 23;
	DiamondInheritanceDerive.m_cBase4Memeber = 24;
	DiamondInheritanceDerive.m_cDiamondInheritanceDeriveMemeber = 30;

	//结构大小
	STREXE_D(sizeof(DiamondInheritanceDerive));//x64-68;	x86-40;

	//DiamondInheritanceDerive Function
	pFun* DiamondInheritanceDeriveVptr = nullptr;	
	//Base Function
	pFun* BaseF1 = nullptr;
	int nPointerSize = 0;

#ifdef _WIN64
	
	long long *llV_ptr = (long long*)&DiamondInheritanceDerive;
	//首地址
	std::cout << "VPtr地址ll:" << std::hex << *llV_ptr << std::endl;
	std::cout << "&DiamondInheritanceDerive:" << std::hex << &DiamondInheritanceDerive << std::endl;
	STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cDiamondInheritanceDeriveMemeber));
	STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cBaseMemeber));
	STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cBase4Memeber));
	STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cBase3Memeber));

	//DiamondInheritanceDerive Function
	//pFun* DiamondInheritanceDeriveVptr = nullptr;
	BaseVirtualFun_Test* pBaseVPtr = nullptr;
	BaseVirtualFun_Test* pBase4VPtr = nullptr;
	BaseVirtualFun_Test* pBase3VPtr = nullptr;

	//默认构造内的一个指针,占4个字节
	nPointerSize = sizeof(long long);
	DiamondInheritanceDeriveVptr = (pFun*)((char*)(*llV_ptr));
	//虚基类表指针
	long long * pDiamondInheritanceDeriveMem = (long long *)((char*)(&DiamondInheritanceDerive) + nPointerSize);
	long long * pVbptr = (long long *)((char*)(pDiamondInheritanceDeriveMem)+sizeof(char));
	//long long* lBaseV_ptr = (long long*)((char*)(pVbptr) + nPointerSize);// (long long*)((((char*)pDiamondInheritanceDeriveMem) + nPointerSize));
	//BaseF1 = (pFun*)(*lBaseV_ptr);
	long long* BaseMemeber = (long long*)((char*)(&DiamondInheritanceDerive) + sizeof(DiamondInheritanceDerive) - sizeof(char));
	long long* lBaseV_ptr = (long long*)((char*)(&DiamondInheritanceDerive) + sizeof(DiamondInheritanceDerive) - sizeof(char) - nPointerSize);
	//long long * pVbptr = (long long*)((char*)(&DiamondInheritanceDerive) + sizeof(DiamondInheritanceDerive) - sizeof(char) - nPointerSize - nPointerSize);
	BaseF1 = (pFun*)(*lBaseV_ptr);//140699019104880		0x7FF7 0B0D D270

	
	pBaseVPtr = (BaseVirtualFun_Test*)(long long*)(*(long long*)((char*)&DiamondInheritanceDeriveVptr) + 24);
	pBase4VPtr = (BaseVirtualFun_Test*)(long long*)((long long*)((char*)pBaseVPtr+ 32) );
	pBase3VPtr = (BaseVirtualFun_Test*)(long long*)((long long*)((char*)pBase4VPtr+ 40) );

	//DiamondInheritanceDerive函数调用
	std::cout << "DiamondInheritanceDerive函数调用:--------------------------------" << std::endl;
	STREXE_HEX(DiamondInheritanceDeriveVptr);
	(*DiamondInheritanceDeriveVptr)();
	STREXE_HEX(pBaseVPtr);
	BaseVirtualFun_Test BaseF = *(BaseVirtualFun_Test *)(pBaseVPtr);
	(DiamondInheritanceDerive.*BaseF)();
	STREXE_HEX(pBase4VPtr);
	BaseVirtualFun_Test BaseF4_1 = *(BaseVirtualFun_Test *)(pBase4VPtr + 1);//跳过虚析构函数
	(DiamondInheritanceDerive.*BaseF4_1)();
	BaseVirtualFun_Test BaseF4_2 = *(BaseVirtualFun_Test *)(pBase4VPtr + 2);
	(DiamondInheritanceDerive.*BaseF4_2)();
	//STREXE_HEX(pBase3VPtr);
	BaseVirtualFun_Test BaseF3_1 = *(BaseVirtualFun_Test *)(pBase3VPtr + 1);//跳过虚析构函数
	BaseVirtualFun_Test BaseF3_2 = *(BaseVirtualFun_Test *)(pBase3VPtr + 2);
	(DiamondInheritanceDerive.*BaseF3_1)();
	(DiamondInheritanceDerive.*BaseF3_2)();
#else 
#ifdef _WIN32	
	//首地址
	long *lV_ptr = (long *)&DiamondInheritanceDerive;
	std::cout << "VPtr地址l:" << std::hex << *lV_ptr << std::endl;
	std::cout << "&DiamondInheritanceDerive:" << std::hex << &DiamondInheritanceDerive << std::endl;
	STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cDiamondInheritanceDeriveMemeber));
	STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cBaseMemeber));
	STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cBase4Memeber));
	STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cBase3Memeber));

	//默认构造内的一个指针
	nPointerSize = sizeof(long);
	DiamondInheritanceDeriveVptr = (pFun*)(*lV_ptr);
	//虚基类表指针
	long * pDiamondInheritanceDeriveMem = (long *)((char*)(&DiamondInheritanceDerive) + nPointerSize);
	long * pVbptr = (long *)(((char*)pDiamondInheritanceDeriveMem) + sizeof(char));
	long* lBaseV_ptr = (long*)((((char*)pVbptr) + nPointerSize));
	BaseF1 = (pFun*)(*lBaseV_ptr);
	long* BaseMemeber = (long*)((char*)lBaseV_ptr + nPointerSize);
			
	pFun* pBaseVPtr = nullptr;
	pFun* pBase4VPtr = nullptr;
	pFun* pBase4VBPtr = nullptr;
	pFun* pBase3VPtr = nullptr;
	
	pBaseVPtr = (pFun*)(((char*)DiamondInheritanceDeriveVptr) + 12);
	pBase4VPtr = (pFun*)(((char*)pBaseVPtr) + 16);
	pBase3VPtr = (pFun*)(((char*)pBase4VPtr) + 20);

	//DiamondInheritanceDerive函数调用
	std::cout << "DiamondInheritanceDerive函数调用:--------------------------------" << std::endl;
	STREXE_HEX(DiamondInheritanceDeriveVptr);
	(*DiamondInheritanceDeriveVptr)();	
	STREXE_HEX(pBaseVPtr);
	(*pBaseVPtr)();	
	STREXE_HEX(pBase4VPtr);
	(*(pBase4VPtr + 1))();//跳过虚析构函数
	(*(pBase4VPtr + 2))();
	STREXE_HEX(pBase3VPtr);
	(*(pBase3VPtr + 1))();//跳过虚析构函数
	(*(pBase3VPtr + 2))();


	STREXE_HEX((long *)(((char*)lV_ptr) + 8));
	STREXE_D((char)(*(((char*)lV_ptr) + 8)));
	STREXE_HEX((long *)(((char*)lV_ptr) + 8 + 9));
	STREXE_D((char)(*(((char*)lV_ptr) + 8 + 9)));
	STREXE_HEX((long *)(((char*)lV_ptr) + 8 + 9 + 9));
	STREXE_D((char)(*(((char*)lV_ptr) + 8 + 9 + 9)));
	STREXE_HEX((long *)(((char*)lV_ptr) + 8 + 9 + 9 + 13));
	STREXE_D((char)(*(((char*)lV_ptr) + 8 + 9 + 9 + 13)));
	
	STREXE_HEX(lV_ptr);
	STREXE_HEX(*lV_ptr);
	pFun *pVirtualFun3 = (pFun*)(*(long *)(((char*)lV_ptr) /*+ nPointerSize*/));
	STREXE_HEX(pVirtualFun3);
	//派生类新增虚函数
	(*(pVirtualFun3))(); //FDiamondInheritanceDerive::VirtualFun3()
	//m_cDiamondInheritanceDeriveMemeber
	STREXE_HEX((long *)(((char*)lV_ptr) + 2 * nPointerSize));
	STREXE_D((char)(*(((char*)lV_ptr) + 2 * nPointerSize)));
	//4个未知空间????vtordisp

	//vbptr
	long* vbptr = (long *)((lV_ptr + 1));
	int nDerive2VBPtr = (int)(*(((long*)(*vbptr))));
	STREXE_D(nDerive2VBPtr);//nDerive2VBPtr: -4
	//Base
	int nBase2VBPtr = (int)(*(((long*)(*vbptr)) + 1));
	STREXE_D(nBase2VBPtr);//nBase2VBPtr: 9
	long* pBaseBPtr = (long*)(((char*)vbptr) + nBase2VBPtr);
	pFun * pBaseVirtualFun1 = (pFun *)(*pBaseBPtr);
	(*pBaseVirtualFun1)();//FDiamondInheritanceDerive::BaseVirtualFun1()
	pFun * pBaseVirtualFun2 = (pFun *)(*pBaseBPtr) + 1;
	(*pBaseVirtualFun2)(); //FBase::BaseVirtualFun2()
	//m_cBaseMemeber
	long* pm_cBaseMemeber = pBaseBPtr + 1;
	STREXE_HEX(pm_cBaseMemeber);
	STREXE_D((char)(*pm_cBaseMemeber));
	
	//Base4
	int nBase42VBPtr = (int)(*(((long*)(*vbptr)) + 2));
	STREXE_D(nBase42VBPtr);//nBase42VBPtr: 14
	long* pBase4BPtr = (long*)(((char*)vbptr) + nBase42VBPtr);
	pFun * pBase4VirtualFun1 = (pFun *)(*pBase4BPtr) + 1;//跳过虚析构
	(*pBase4VirtualFun1)(); //FBase4::BaseVirtualFun1()
	pFun * pBase4VirtualFun2 = (pFun *)(*pBase4BPtr) + 2;
	(*pBase4VirtualFun2)(); //FBase4::BaseVirtualFun2()
	//Base4::vbptr
	long* pBase4_vbptr = pBase4BPtr + 1;
	int nVBPtr42VPtr = (int)(*(((long*)(*pBase4_vbptr))));
	STREXE_D(nVBPtr42VPtr);//nVBPtr42VPtr: -4
	int nVBPtr42BaseVPtr = (int)(*(((long*)(*pBase4_vbptr)) + 1));
	STREXE_D(nVBPtr42BaseVPtr);//nVBPtr42BaseVPtr: -9
	//m_cBase4Memeber
	long* pm_cBase4Memeber = pBase4BPtr + 1 + 1;
	STREXE_HEX(pm_cBase4Memeber);
	STREXE_D((char)(*pm_cBase4Memeber));
	//4个未知空间????vtordisp

	//Base3
	int nVBPtr2Base3VPtr = (int)(*(((long*)(*vbptr)) + 3));
	STREXE_D(nVBPtr2Base3VPtr);//nVBPtr2Base3VPtr: 27
	long* pBase3BPtr = (long*)(((char*)vbptr) + nVBPtr2Base3VPtr);
	pFun * pBase3VirtualFun1 = (pFun *)(*pBase3BPtr) + 1;//跳过虚析构
	(*pBase3VirtualFun1)(); //FDiamondInheritanceDerive::Base3VirtualFun1()
	pFun * pBase3VirtualFun2 = (pFun *)(*pBase3BPtr) + 2;
	(*pBase3VirtualFun2)(); //FBase3::BaseVirtualFun2()	
	//Base3::vbptr
	long* pBase3_vbptr = pBase3BPtr + 1;
	int nVBPtr32VPtr = (int)(*(((long*)(*pBase3_vbptr))));
	STREXE_D(nVBPtr32VPtr);//nVBPtr32VPtr: -4
	int nVBPtr32BaseVPtr = (int)(*(((long*)(*pBase3_vbptr)) + 1));
	STREXE_D(nVBPtr32BaseVPtr);//nVBPtr32BaseVPtr: -22
	//m_cBase3Memeber
	long* pm_cBase3Memeber = pBase3BPtr + 1 + 1;
	STREXE_HEX(pm_cBase3Memeber);
	STREXE_D((char)(*pm_cBase3Memeber));//(char)(*pm_cBase3Memeber): 23
	//4个未知空间????vtordisp
#endif
#endif

	std::cout << "------------------------------------DiamondInheritanceDerive_Test-------------------------End" << std::endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值