奇思妙想:如何通过this指针分析出C++对象的内存布局?
在不知道类定义的情况下,如何通过this指针分析出对象的内存布局?
要求从this指针和内存快照分析出以下内容:
(1)VPTR
(2)VTABLE。有哪些virtual function
(3)对象大小
(4)继承关系或组合关系。
(5)成员变量的总大小。
(6)基类对象的上述内容.
(7)组合对象的上述内容.
这个问题来源于一个突然的想法,感觉无从下手,又觉得应该有办法解决。不知道大虾能否找到合理的分析过程。
以VC6为例,
只知道this指针为0x00373e78。
对象内存快照
0373E60 00000000
00373E64 00000000
00373E68 00000008
00373E6C 00000001
00373E70 0000003E
00373E74 FDFDFDFD
00373E78 0046F048 =====00373E78是THIS指针。0046F048是指向虚函数表的指针。
00373E7C 12345678 ======成员变量
00373E80 FDFDFDFD
下面属于未知内容。
/////////未知内容///////////////////////////////////////////
某个类定义如下:
class BVirtualObject
{
public:
BVirtualObject(){ m_value = 0x12345678;}
virtual ~BVirtualObject(){}
private:
int m_value;
};
对象大小为8个字节。
sizeof(BVirtualObject) 0x00000008
对象结构
- virobj 0x00373e78 =====THIS指针
- __vfptr 0x0046f048 const BVirtualObject::`vftable '
[0] 0x00401285 BVirtualObject::`vector deleting destructor '(unsigned int)
m_value 0x12345678
/////////未知内容///////////////////////////////////////////
那么,对于下面这个比较复杂的对象,如何分析呢?
只知道this指针为0x00373408,
对象内存快照
003733F0 00000000
003733F4 00000000
003733F8 0000000C
003733FC 00000001
00373400 0000003D
00373404 FDFDFDFD
00373408 00470050
0037340C 12345678
00373410 12345679
00373414 FDFDFDFD
00373418 ABABABAB
虚函数表快照
00470044 0000003D
00470048 00401217
0047004C 004012CB
00470050 004012C1
00470054 00401320
00470058 00000000
下面是对应的类定义,分析时,我们并不知道下面的全部信息。
该如何下手呢?
////////////////////////////////////////////////////////////
/////////未知内容///////////////////////////////////////////
类定义如下:
class BDerivedFromVirtualObject2 : public BVirtualObject
{
public:
BDerivedFromVirtualObject2(){ m_value = 0x12345679; }
virtual ~BDerivedFromVirtualObject2(){}
virtual void VF1()
{
cout < < "BDerivedFromVirtualObject2::VF1() called. " < < endl;
}
private:
int m_value;
};
对象大小为12个字节。
sizeof(BDerivedFromVirtualObject2) 0x0000000c
对象结构
- vo2 0x00373408
- BVirtualObject {...}
- __vfptr 0x00470050 const BDerivedFromVirtualObject2::`vftable '
[0x0] 0x004012c1 BDerivedFromVirtualObject2::`vector deleting destructor '(unsigned int)
m_value 0x12345678
m_value 0x12345679
/////////未知内容///////////////////////////////////////////
////////////////////////////////////////////////////////////
不求甚解。
[解决办法]
顶
[解决办法]
UP
[解决办法]
(1)VPTR //一般为对象的开始处. 这样得到它的值:(void *)(*((unsigned int*)(&Obj)))
(2)VTABLE。有哪些virtual function //根据VPTR可以找到VTABLE,但VTABLE并不记录它本身的大小,访问它的虚函数是编译时的规则
(3)对象大小 //编译时的规则,,连编译器也要在看到类定义时才能知道,可以在编译时sizeof得到.
(4)继承关系或组合关系。 //编译时的规则,连编译器也要在看到类定义时才能知道.
(5)成员变量的总大小。 //编译时的规则,连编译器也要在看到类定义时才能知道.
(6)基类对象的上述内容.
(7)组合对象的上述内容.
[解决办法]
有这功夫,先看了《深度探索C++对象模型》再说吧。
[解决办法]
up
[解决办法]
要是有基类和派生类所有的this指针倒是可以得到
1 3 4 5这几项的内容的.至于第二项,是没有办法分析出来的
[解决办法]
不同的编译器实现也不一样
[解决办法]
这个应该很麻烦吧?
其实虚拟基类和虚拟函数指针本身的位置也不确定
[解决办法]
即使程序本身,找成员也要通过偏移量的
现在就一个地址却想定位出成员之类东西来,觉得不太现实
[解决办法]
其中那么多项,就算搞清楚了,又有什么实用意义呢?
[解决办法]
C++标准里面没这些玩艺,编译器的不同甚至编译参数不同对象内存布局也可能不一样。