C++中如何获取虚表和虚函数的地址

news2024/12/27 14:14:36
获取虚函数的地址

虚函数是C++中用于实现多态的一种机制,该机制的原理在此不做赘述。本文主要讨论如何获取虚表以及虚函数的地址

class ClassA {
private:
    int _a;
    double _b;
public:
    ClassA(int a, double b) : _a(a), _b(b) { }
    virtual int funcA(int a) { return a; }
    virtual double funcB() { return _b; }
};

在这里插入图片描述

#include <iostream>

#define PRINT(val) \
    std::cout << #val << ": " << val << std::endl

int main()
{
    ClassA classA(3, 1.2);
    intptr_t* vptr = reinterpret_cast<intptr_t*>(&classA);  // 虚表指针
    intptr_t vtable_addr = *vptr; // 解引用,获取虚表的地址
    intptr_t* virtual_func_ptr = reinterpret_cast<intptr_t*>(vtable_addr); // 指向第一个虚函数地址
    intptr_t funcA_addr  = *virtual_func_ptr; // 解引用,获取funcA的地址
    intptr_t funcB_addr  = *(virtual_func_ptr + 1); // 解引用,获取funcB的地址
    intptr_t funcB_addr2 = *reinterpret_cast<intptr_t*>(vtable_addr + sizeof(intptr_t)); // funcB的地址

    std::cout << std::hex;
    PRINT(vptr);
    PRINT(vtable_addr);
    PRINT(funcA_addr); 
    PRINT(funcB_addr);
    PRINT(funcB_addr2);

    typedef int (*FuncAType)(ClassA*, int);
    typedef double (*FuncBType)(ClassA*);
    FuncAType funcA = (FuncAType)funcA_addr;
    FuncBType funcB = (FuncBType)funcB_addr;
    FuncBType funcB2 = (FuncBType)funcB_addr2;

    int a = funcA(&classA, 0x21);
    double b = funcB(&classA);
    double b2 = funcB2(&classA);
    PRINT(a);
    PRINT(b);
    PRINT(b2);

    return 0;
}

输出结果如下:
在这里插入图片描述

  • vptr:虚表指针,指向虚表,解引用后即可获得虚表的地址值。

  • vtable_addr:虚表地址,存放在vptr所指向的内存中。

  • virtual_func_ptr:将虚表地址vtable_addr强转为指针,指向虚函数地址。

  • funcA_addr:将virtual_func_ptr解引用,即得到第一个虚函数的地址。

  • funcB_addr:将virtual_func_ptr + 1解引用,即得到第二个虚函数的地址。

  • funcB_addr2:将vtable_addr + sizeof(intptr_t),先强转为指向虚函数地址的指针,再解引用,即得到第二个虚函数的地址,对于32为系统sizeof(intptr_t)的值为4,64位系统则等于8。从输出结果中可以看出,funcB的地址值是0x400e88,funcA的地址值是0x400e78,两者的差值正好是8,所以此处sizeof(intptr_t)的值为8。

  • 对于funcB_addr和funcB_addr2的理解

    • 我们可以按照如下方式去理解:

      int* p = new int[4]{1, 2, 3, 4};
      int p0 = *p;       // 第一个元素,很容易理解
      int p1 = *(p + 1); // 第二个元素,很容易理解
      
      intptr_t addr = reinterpret_cast<intptr_t>(p); // 得到指针p的地址值
      // 每4个(sizeof(int)为4)字节存放一个元素,所以addr+4*i即表示第i+1个元素的地址。
      int p1_2      = *reinterpret_cast<int*>(addr + sizeof(int)); // 第二个元素的值
      
      PRINT(p0); // 输出1
      PRINT(p1); // 输出2
      PRINT(p1_2); // 输出2
      

      funcB_addr就类似p1,funcB_addr2类似于p1_2,virtual_func_ptr类似于p,vtable_addr类似于addr,虚函数地址即为元素,每个元素占sizeof(intptr_t)个字节。

虚函数在虚表中的偏移值
auto funcA_ptr = &ClassA::funcA;
auto funcB_ptr = &ClassA::funcB;
intptr_t funcA_offset = reinterpret_cast<intptr_t>((intptr_t&)funcA_ptr);
intptr_t funcB_offset = reinterpret_cast<intptr_t>((intptr_t&)funcB_ptr);

PRINT(funcA_offset); // 输出1,实际偏移值为0
PRINT(funcB_offset); // 输出9,实际偏移值为8
  • 可以看出funcA的偏移值是funcA_offset - 1,funcB的偏移值是funcB_offset - 1。

  • 可以通过上述偏移值和虚表指针来确定虚函数的实际地址。而不是通过给定值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1185712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式之组合模式-创建层次化的对象结构

目录 概述概念主要角色应用场景 组合模式的实现类图NS图基本代码组合模式的精髓意外收获&#xff08;❀❀&#xff09; 应用示例-公司组织架构管理需求结构图代码 组合模式的优缺点优点缺点 总结 概述 概念 组合模式是一种结构型设计模式&#xff0c;它允许将对象组合成树形结…

xshell和linux什么关系,其实很简单

如果你是从事网络安全相关的工作人员&#xff0c;那你一定对很多人xshell和linux这两词很熟悉&#xff0c;那么xshell和linux究竟是什么关系呢&#xff1f;今天就让小编给你详细讲讲。 xshell和linux什么关系 一、xshell和linux什么关系 Xsehll是一款在Windows平台上运行的远…

在WSL2中安装多个Ubuntu实例

参考&#xff1a;How to install multiple instances of Ubuntu in WSL2 本文主要内容 第一步&#xff1a;在 WSL2 中安装最新的 Ubuntu第二步&#xff1a;下载适用于 WSL2 的 Ubuntu 压缩包第三步&#xff1a;在 WSL2 中安装第二个 Ubuntu 实例第四步&#xff1a;登录到第二个…

pyspark将数据多次插入表的时候报错

代码 报错信息 py4j.protocol.Py4JJavaError: An error occurred while calling o129.sql. : org.apache.spark.sql.catalyst.parser.ParseException: mismatched input INSERT expecting <EOF>(line 12, pos 0) 原因 插入语句结束后没有加&#xff1b;结尾 把两个&am…

自定义注解+拦截器/AOP切面 实现权限管理

一、通过拦截器实现 1 权限表 为了方便&#xff0c;我直接用的现成的权限表&#xff0c;这是表结构 2 自定义注解 首先&#xff0c;创建一个自定义注解&#xff0c;用于controller层的方法或类上 // Target表示该注解可以用在方法和类上 Target({ElementType.METHOD, Ele…

5.注释和文档

本文讲解 Java 中的注释以及文档 ~ 文章目录 1. 注释1.1 引言1.1.1 何为注释&#xff1f;1.1.2 注释有何用&#xff1f; 1.2 类注释1.2 方法注释 2. 文档 1. 注释 1.1 引言 1.1.1 何为注释&#xff1f; 在我看来&#xff0c;注释无非是对一行或多行代码作的解释罢了。它能让…

Java学习_day08_finalnativeabstract接口

文章目录 final关键字注意 native关键字abstract关键字抽象类定义继承 接口定义实现 final关键字 final关键字表示常量&#xff0c;其值在程序运行期间不会改变。 final用来修饰变量&#xff0c;可以是静态变量&#xff0c;也可以是成员变量&#xff0c;也可以是局部变量&…

连接图书馆wifi无法验证如何解决

我们去图书馆连接wifi&#xff0c;无法验证自己身份&#xff0c;怎么办&#xff1f; 一般是电脑怀疑是不安全&#xff0c;进行了拦截。 我们点击不安全 再点击 与此站点的连接不安全 &#xff0c; 了解详情就可以显示登陆界面了&#xff0c;

点击清空按钮表单数据不能清空

清空选项只能清空角色和状态的数据,无法清空用户名的数据, 经过排查后发现 username这个单词写错了,导致点击清空searchFormRef?.resetFields()不能清空用户名数据

算法之路(一)

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 :算法小能手 &#x1f606;今日分享 : 如何学习&#xff1f; 在学习的过程中&#xff0c;不仅要知道如何学习&#xff0c;还要知道避免学习的陷阱。1. 睡眠不足&#xff1b;2. 被动学习和重读&#xff1b;3. 强调标记或画线&am…

接口--抽象方法

回答问题&#xff1a; 1.接口是什么&#xff1f; 2.接口中可以包含什么内容&#xff1f; 3.如何定义接口格式&#xff1f; 4.接口定义抽象方法格式&#xff1f; Code //接口是公共规范标准&#xff0c;类似于“模具” //如何定义接口格式&#xff1f;/** public interface 接…

【Qt之QVariant】使用

介绍 QVariant类类似于最常见的Qt数据类型的联合。由于C禁止联合类型包括具有非默认构造函数或析构函数的类型&#xff0c;大多数有趣的Qt类不能在联合中使用。如果没有QVariant&#xff0c;则QObject::property()和数据库操作等将会受到影响。 QVariant对象同时持有一个单一…

View 自定义 - 路径 Path

参考文章 一、概念 用于描述顺序 & 区域&#xff0c;单使用无法产生效果。 图形绘制的本质是先画点再将点连接起来&#xff0c;所以点与点之间是存在一个先后顺序的。图形的方向影响的是&#xff1a;添加图形时确定闭合顺序(各个点的记录顺序)、图形的渲染结果(是判断图形…

ArcGIS进阶:水源涵养功能分级评价操作

首先抛出水源涵养重要性评价的公式&#xff1a;水源涵养量降雨量-蒸散发量-地表径流量&#xff0c;其中地表径流量降雨量*平均地表径流系数 声明&#xff1a;以下数据来源于来自于牛强老师书籍&#xff08;城乡规划GIS技术&#xff09;。 以下给出重要性评价阈值表&#xff1…

『MySQL快速上手』-⑥-表的约束

文章目录 1.空属性2.默认值3.列描述4.zerofill5.主键6.自增长7.唯一键8.外键9.综合案例 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。 1.空…

高校为什么需要企业数据库?

随着信息化数字化的发展&#xff0c;企业数据库已经成为高校不可或缺的一部分。企业数据库一般整合了多维度企业数据信息。比如&#xff0c;艾思依托丰富的数据沉淀和领先的模型算法&#xff0c;打造“1N”产业大数据平台&#xff0c;包含“1个企业数据中心”一一涵盖全国2.4亿…

计算机提示找不到concrt140.dll怎么办,分享4个有效的修复方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示或者系统崩溃的情况。其中&#xff0c;concrt140.dll是一个常见的错误提示&#xff0c;这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些修复措施。本文将介绍4个修复conc…

基于显著性的无人机多光谱图像语义杂草检测与分类

Saliency-Based Semantic Weeds Detection and Classification Using UAV Multispectral Imaging(2023&#xff09; 摘要1、介绍2、相关工作2.1 监督学习2.2 半监督学习2.3 无监督学习 3、方法3.1 贡献3.2 PC/BC-DIM NEURAL NETWORK&#xff08;预测编码/有偏竞争-分裂输入调制…

20个Python实用小技巧!来自十年老程序员的推荐~

文章目录 1.用itertools排列2.单行条件表达式3. 反转字符串4. 使用 Assert 处理异常5. 对多个输入使用拆分6. 用 zip() 转置矩阵7. 资源上下文管理器8. 下划线作为分隔符9. 尝试 f 字符串格式10.用这个技巧交换整数11. 使用 lambda 代替函数12.多次打印无循环13. 将字符串解包为…

基于机器学习的 ICU 脑血管疾病死亡风险智能预测系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 重症患者或重大手术后的患者在重症监护室&#xff08;ICU&#xff09;内通过多种生命支持系统以维持生理功能。患者在ICU 内会被频繁持续的记录生命体征和实验室测量等多种数据。由于高频…