C++虚函数表在内存中的位置

                          C++虚函数表在内存中的位置

                                                                                                                                                                            by Loren Zhai

前段时间有人问C++虚函数表保存在内存的什么位置,下面是调试的相关信息。

1. 例子代码

class CA
{
public:
virtual void Func_Virtual11();
virtual void Func_Virtual22();

private:
int m_ia;
};
class CB : public CA
{
void Func_Virtual11();
virtual void Func_Virtual33();
};

class CD : public CB
{
void Func_Virtual11();
void Func_Virtual22();
void Func_Virtual33();
};
void CA::Func_Virtual11()
{
printf("Hello World! CA 11/n");
}
void CA::Func_Virtual22()
{
printf("Hello World! CA 22/n");
}
void CB::Func_Virtual11()
{
printf("Hello World! CB 11/n");
}
void CB::Func_Virtual33()
{
printf("Hello World! CB 33/n");
}
void CD::Func_Virtual11()
{
printf("Hello World! CD 11/n");
}
void CD::Func_Virtual22()
{
printf("Hello World! CD 22/n");
}
void CD::Func_Virtual33()
{
printf("Hello World! CD 33/n");
}
void Demo()
{
CA* m_pCA = new CB();
CA* m_pCD = new CD();

m_pCA->Func_Virtual11();
m_pCA->Func_Virtual22();

m_pCD->Func_Virtual11();
m_pCD->Func_Virtual22();

  sprintf(chdata, ("chdata=%x m_pCD=%x "),m_pCA,m_pCD); //这里的Trace很重要,后面的所有分析都是基于这两个内存值。
}

2. 调试分析

2.1, demo函数反汇编

  72 004010c2 8b07 mov eax,dword ptr [edi]
  72 004010c4 8bcf mov ecx,edi
  72 004010c6 ff10 call dword ptr [eax]
  73 004010c8 8b17 mov edx,dword ptr [edi]
  73 004010ca 8bcf mov ecx,edi
  73 004010cc ff5204 call dword ptr [edx+4]
  75 004010cf 8b06 mov eax,dword ptr [esi]
  75 004010d1 8bce mov ecx,esi
  75 004010d3 ff10 call dword ptr [eax]
  76 004010d5 8b16 mov edx,dword ptr [esi]
  76 004010d7 8bce mov ecx,esi
  76 004010d9 ff5204 call dword ptr [edx+4]

2.1 程序关键Log

chdata=250e80 m_pCD=250e98

2.3 寻找虚函数表e

0:000> ln poi(250e80)
(004070e8) CVirtualClassDemo!CB::`vftable'

0:000> ln poi(250e98)
(004070dc) CVirtualClassDemo!CD::`vftable'

0:000> dds 004070dc-0x10
004070cc 00000002
004070d0 0000004d
004070d4 00000000
004070d8 0000b000
004070dc00401040 CVirtualClassDemo!CD::Func_Virtual11 
004070e0 00401050 CVirtualClassDemo!CD::Func_Virtual22 
004070e4 00401060 CVirtualClassDemo!CD::Func_Virtual33 
004070e8 00401020 CVirtualClassDemo!CB::Func_Virtual11 
004070ec 00401010 CVirtualClassDemo!CA::Func_Virtual22 
004070f0 00401030 CVirtualClassDemo!CB::Func_Virtual33 
004070f4 00000000
004070f8 ffffffff
004070fc 0040126d CVirtualClassDemo!mainCRTStartup+0xc0

 

0:000> !address 004070dc  
Usage: Image
Allocation Base: 00400000
Base Address: 00407000
End Address: 00408000
Region Size: 00001000
Type: 01000000 MEM_IMAGE
State: 00001000 MEM_COMMIT
Protect: 00000002 PAGE_READONLY

3. 结论:

1. 虚函数表保存在只读内存段中。

2. 具体的虚表内容,在编译时就决定了整个继承链上V-table的信息。中间的某个子类,它的V-tabel是整个V-table的一个子结构。因为包含虚函数的类的数据结构,第一个DWORD保存了V-table的地址,同时这个值是在创建类时确定了。通过上面Demo函数的反汇编,就能清楚是如何找到当前虚函数的具体的实现实现函数了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值