首页
社区
课程
招聘
[原创] C++虚函数内存模型分析
发表于: 2025-6-6 11:06 514

[原创] C++虚函数内存模型分析

2025-6-6 11:06
514

编写测试代码如下,定义一个基类Base,并第一个虚函数 func。定义一个子类Derived,继承基类Base,并覆盖虚函数 func

main函数中创建临时对象 Derived, 并使用基类指针指向Derived对象,通过指针调用虚函数 func。调用结果如下:


指令层面分析


首先进入分析main函数代码:

上述是main函数的汇编指令,由于是局部申明对象,申明后的对象在栈中保存,保存地址是 rbp + 0x10,将该地址通过rdi寄存器传参,然后调用Derived的构造函数。调用完构造函数后,先取对象首地址处的值拿到虚表指针,然后取虚表指针的第一个值,拿到虚函数地址,并调用虚函数。


接着进入到Derived的构造函数处分析:


这是一个套壳的构造函数,实际上只是对真实构造函数的调用,进入到真实构造函数处:

构造函数的参数就是对象的首地址,也就是this指针,构造函数先调用基类Base的构造函数,调用完成后,将Derived类基表+0x10处的地址保存在了对象首地址处。看下基类的构造函数:

基类的构造函数同样是将基类的虚表地址+0x10 保存在了对象首地址处。那么继续看下这两个类的虚表数据:

虚表的首地址是 0,然后是该类的type_info,虚表+0x10处才是第一个虚函数的地址。最后面保存的是盖类的析构函数地址。


1、如果类中有定义虚函数,编译器会生成该类的虚函数表,并在创建对象时,在对象的头部保存虚指针。

2、对象初始化时,在对象的构造函数中,会调用基类的构造函数,在构造函数中会初始化虚指针,基类构造函数中先初始化虚指针,然后在子类构造函数中初始化时,覆盖了基类构造函数中初始化的虚指针值。

3、虚函数不能定义成构造函数,因为虚函数通过虚指针来定位虚表中的虚函数,而虚指针在构造函数完成时才会完成初始化。

4、虚表是一个指针数组,gcc实现中虚表第一个指针保留0,第二个指针存储typeinfo信息指针,第三个指针开始存放虚函数。


上述代码在前面的基础上,新增了两个类用于多继承,其中Base2中的虚方法没有覆盖,同样直接分析对象的构造函数:


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2025-6-6 11:25 被CCTV果冻爽编辑 ,原因:
收藏
免费 23
支持
分享
最新回复 (5)
雪    币: 2276
活跃值: (5453)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
牛逼
2025-6-6 18:37
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
6plus
2025-6-9 10:39
0
雪    币: 178
活跃值: (2486)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
4
2025-6-9 10:49
0
雪    币: 92
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
66666
2025-6-9 14:10
0
雪    币: 4561
活跃值: (4056)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
回复来看看,先谢过楼主!
2025-6-9 14:41
0
游客
登录 | 注册 方可回帖
返回