破译vtable转储

2024-04-29

我正在“玩”C++ 中的虚拟继承,我想知道类对象是如何布局的。 我有这三个课程:

class A {
private:
    int a;
public:
    A() {this->a = 47;}
    virtual void setInt(int x) {this->a = x;}
    virtual int getInt() {return this->a;}
    ~A() {this->a = 0;}
};

class B {
private:
    int b;
public:
    B() {b = 48;}
    virtual void setInt(int x) {this->b = x;}
    virtual int getInt() {return this->b;}
    ~B() {b = 0;}
};

class C : public A, public B {
private:
    int c;
public:
    C() {c = 49;}
    virtual void setInt(int x) {this->c = x;}
    virtual int getInt() {return this->c;}
    ~C() {c = 0;}
};

(我认为他们是正确的:p)

I used -fdump-class-hierarchy使用 g++,我得到了这个

Vtable for A
A::_ZTV1A: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1A)
16    A::setInt
24    A::getInt

Class A
   size=16 align=8
   base size=12 base align=8
A (0x10209fb60) 0
    vptr=((& A::_ZTV1A) + 16u)

Vtable for B
B::_ZTV1B: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1B)
16    B::setInt
24    B::getInt

Class B
   size=16 align=8
   base size=12 base align=8
B (0x1020eb230) 0
    vptr=((& B::_ZTV1B) + 16u)

Vtable for C
C::_ZTV1C: 8u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1C)
16    C::setInt
24    C::getInt
32    (int (*)(...))-0x00000000000000010
40    (int (*)(...))(& _ZTI1C)
48    C::_ZThn16_N1C6setIntEi
56    C::_ZThn16_N1C6getIntEv

Class C
   size=32 align=8
   base size=32 base align=8
C (0x1020f5080) 0
    vptr=((& C::_ZTV1C) + 16u)
  A (0x1020ebd90) 0
      primary-for C (0x1020f5080)
  B (0x1020ebe00) 16
      vptr=((& C::_ZTV1C) + 48u)

现在那些到底是什么(int (*)(...))-0x00000000000000010 and C::_ZThn16_N1C6setIntEi and (int (*)(...))0?? 有人可以解释一下转储吗?

谢谢。


我不能 100% 确定这个答案是正确的,但这是我的最佳猜测。

当您有一个多重且非虚拟继承的类时,该类的布局通常是第一个基本类型的完整对象,然后是第二个基本类型的完整对象,然后是对象本身的数据。如果您查看 B,您可以看到 A 对象的 vtable 指针,如果您查看 C,您可以看到 A 和 B 对象都有指向 vtable 的指针。

因为对象是这样布局的,这意味着如果您有一个B*指针指向一个C对象,指针实际上不会位于对象的基址;相反,它会指向中间的某个地方。这意味着如果您需要将对象转换为A*,你需要调整B*指针一定量以将其跳回到对象的开头。为了做到这一点,编译器需要在某处编码您需要跳回以到达对象开头的字节数。我认为第一个(int(*)(...))实际上只是您需要查看才能到达对象开头的原始字节数。如果你注意到的话,对于Avtable this 指针为 0(因为 A 的 vtable 位于对象的开头,对于Bvtable(因为它也位于对象的开头。但是,请注意Cvtable 有两部分 - 第一部分是 vtableA,它的第一个疯狂条目也为零(因为如果你在Avtable,不需要做任何调整)。然而,在该表的前半部分之后似乎是Bvtable,并注意它的第一个条目是十六进制值-0x10。如果你看一下C对象布局,你会注意到Bvtable指针后16个字节A虚函数表指针。这-0x10值可能是您需要跳回的校正偏移量Bvtable 指针返回到对象的根。

每个 vtable 的第二个疯狂条目似乎是指向 vtable 本身的指针。请注意,它始终等于 vtable 对象的地址(比较 vtable 的名称和它所指向的内容)。如果您想要进行任何类型的运行时类型识别,这将是必要的,因为这通常涉及查看 vtable 的地址(或至少是靠近其前面的地址)。

最后,至于为什么在末尾有神秘命名的 setInt 和 getInt 函数Cvtable,我很确定那是因为Ctype 继承了两组不同的函数,名为setInt and getInt- 一通A和一通B。如果我不得不猜测,这里的修改是为了确保编译器内部可以区分两个虚拟函数。

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

破译vtable转储 的相关文章

随机推荐

  • 操作数类型冲突:uniqueidentifier 与 int 不兼容

    当我尝试创建下面的存储过程时 出现以下错误 操作数类型冲突 uniqueidentifier 与 int 不兼容 我不清楚是什么原因导致了这个错误 UserID 实际上是我所有表中的一个 int 有人可以告诉我我做错了什么吗 create
  • Pygame 简单循环在 Mac 上运行速度非常慢

    E 在 OS X 和 Linux 上进行相同的测试后 我可以确认以下情况仅发生在 OS X 上 在 Linux 上 它实际上以 1000 fps 的速度运行 正如我碰巧想知道的那样 有什么解释吗 感谢 TextMate 我更喜欢在 Mac
  • Spring Zuul:动态禁用到服务的路由

    我正在尝试禁用在运行时向 Eureka 注册的微服务的 Zuul 路由 我正在使用 Spring Boot 这是一个例子 localhost hello localhost world 这两个是注册的微服务 我想在运行时禁用到其中之一的路由
  • 迁移到 AndroidX 后,应用程序崩溃并尝试在空引用上调用 androidx.fragment.app.FragmentManagerImpl.isDestroyed()

    完整的堆栈仅包括 android 核心代码 java lang NullPointerException Attempt to invoke virtual method boolean androidx fragment app Frag
  • 如何将散景 vbar 图表参数与 groupby 对象一起使用?

    Question 下面的代码是来自 bokeh 文档的分组 vbar 图表示例 这个例子中有一些我无法理解的地方 Factor cmap 和 vbar 中的 cyl mfr 来自哪里 mpg mean 是否计算 mpg 列的平均值 如果那么
  • 使用 selenium 登录 stackoverflow 可以正常工作,但使用 scrapy python 则不行。如何使用无头浏览登录?

    我一直在尝试自动登录 stackoverflow 来学习网络抓取 首先我尝试了 scrapy 但使用下面的代码我并没有那么幸运 import scrapy from scrapy utils response import open in
  • doctest (python) 中的模拟 Y (from X import Y)

    我正在尝试创建一个带有模拟功能的文档测试 该功能位于单独的模块中 导入如下 from foomodule import foo def bar gt gt gt from minimock import mock gt gt gt mock
  • Autodesk Forge Viewer 如何获取线起点/终点的坐标

    我正在尝试在 forge 查看器中突出显示房间 在 Revit 中 我创建了代表房间边界的线条 转换为 svf 后 我知道这些行的 dbids 现在我想知道这些线的起点和终点 顶点 以便我可以创建房间边界的 Three Shape 编辑 我
  • PyCharm 上的远程调试

    我的源代码存储在远程计算机上 我想远程编码和调试我的Python源代码 我应该如何配置PyCharm启用远程调试 对于远程调试 您需要将源代码复制到本地计算机 设置项目 配置到远程计算机的部署并添加远程 Python 解释器以在远程系统上运
  • Xcode:如何让目标设置从项目继承

    我们的目标设定是继承 https stackoverflow com a 1642738 47281从项目设置 我们更改了目标设置 中断继承 但现在希望目标再次开始从项目继承 你怎么能这样做呢 清除有问题的目标设置似乎不起作用 清除目标设置
  • MS Access DAO 连接在退出时放弃更改

    因此 我有一个 Access 表单 我在其中使用此 VBA 代码以及与 MySQL 数据库的 DAO 连接 一切都很好 但如果用户关闭表单而不单击 保存 按钮 新记录无论如何都会保存 所以我正在寻找的是 是否有任何方法可以在关闭事件时阻止将
  • 在 Android 中设置 Signalr:崩溃/挂起问题

    我跟着本教程 https whathecode wordpress com 2014 03 20 getting started with the java signalr sdk 为我的 Android 应用程序设置一个 NET 后端来实
  • 如何获取Linux中进程或端口的网络带宽使用情况

    我想获取每个进程的网络带宽使用情况 我找了很多这方面的资料 比如iftop nethogs http nethogs sourceforge net Linux进程浏览器 http sourceforge net projects proc
  • Google Sheets API v4:batchGet 不起作用

    无法使用 batchGet 让 Google Sheets API v4 返回多个范围值 它给出以下错误 尽管文档说它需要 valueRanges 但所有范围和电子表格 ID 都是正确的 额外的参数块必须是 javascript 对象文字
  • 处理 DBNull.Value

    我经常需要处理连接到网格控件的数据表 自定义更新似乎总是产生大量与 DBNull Value 相关的代码 我在这里看到了类似的问题 但认为必须有更好的答案 处理 DBNull 的最佳方法是什么 https stackoverflow com
  • 退格键删除整个跨度元素

    是否可以通过退格键防止跨度删除 div class form control span class correct answer span The correct answer is A 1 to 2 span span class sen
  • F# 是卡牌游戏 AI 的好语言吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 消息 discord.py 中的可点击链接

    我希望我的机器人将消息发送到聊天中 如下所示 await ctx send This country is not supported you can ask me to add it here 但是为了使 这里 成为可点击的链接 在 HT
  • 在函数中使用node-mysql

    我对 Nodejs 很陌生 有一个问题 尝试创建一个函数 该函数将调用我在表中提到其 ID 的任何字段的值 function getUserInfo userID dynamicField var query connection quer
  • 破译vtable转储

    我正在 玩 C 中的虚拟继承 我想知道类对象是如何布局的 我有这三个课程 class A private int a public A this gt a 47 virtual void setInt int x this gt a x v