什么是从虚拟基类继承的虚拟函数的“虚拟 thunk”?

2023-12-19

当我尝试访问从虚拟基类继承的派生类对象的内存布局时,出现了问题。
编程环境:GNU/Linux 3.19.0-32-generic、x86_64
编译器:gcc 4.8.4

//virtual base class
class Base {
public :
    virtual void f() {
        cout << "Base::f()" << endl;
    }
private:
    long x;
};

//derived class
class Derived : public virtual Base {
public:
    virtual void f() {
        cout << "Derived::f()" << endl;
    }
private:
    long y;
};

int main() {
    typedef void (*FUNC)(void);
    Derived d;

    //In my machine, sizeof(long) == sizeof(pointers). My code below is neither portable nor concise. You can just read the annotation.

    //dereference the first element of the first virtual function table(equals to *(vptr1->slot[0]))
    cout << hex << *((long*)*((long*)(&d) + 0) + 0) << endl;
    ((FUNC)*((long*)*((long*)(&d) + 0) + 0))();//invoke Derived::f()

    //dereference the first element of the second virtual function table(equals to *(vptr2->slot[0]))
    cout << hex << *((long*)*((long*)(&d) + 2) + 0) << endl;
    ((FUNC)*((long*)*((long*)(&d) + 2) + 0))();//maybe Derived::f()?

    return 0;
}

当我运行代码时,出现“段错误”:

400c12
Derived::f()
400c3c
segment fault

所以我反汇编了可执行文件。
我在 0x400c3c 中找到了函数 <_ztv0_n24_n7derived1fev>:

0000000000400c3c <_ZTv0_n24_N7Derived1fEv>:
  400c3c:       4c 8b 17                mov    (%rdi),%r10
  400c3f:       49 03 7a e8             add    -0x18(%r10),%rdi
  400c43:       eb cd                   jmp    400c12 <_ZN7Derived1fEv>
  400c45:       90                      nop

在我的终端中对符号进行分解:

> c++filt _ZTv0_n24_N7Derived1fEv
virtual thunk to Derived::f()

那么 Derived::f() 的虚拟 thunk 是什么?为什么会有它呢?


某些函数的虚拟 thunk 是一个辅助函数,用于修复this调用实际函数之前的参数。看这个例子:

Derived *d = new Derived();
// d now points to some address, e.g. 0x6eac40

d->f(); // This calls _ZN7Derived1fEv (Derived::f() directly)

Base *b = d;
// b now points to some other address (!), e.g. 0x6eac50

b->f(); // This calls _ZTv0_n24_N7Derived1fEv (the virtual thunk
        // of Derived::f()), which subtracts some amount from `this`
        // and then jumps to the _ZN7Derived1fEv (Derived::f())

A Base内存中的对象看起来像这样:

      * Pointer to part of Base vtable with Base's virtual functions.
          This vtable contains Base::f()

      * Data of Base class (variable `x`)

A Derived内存中的对象看起来像这样:

   |> * Pointer to part of Derived vtable with Derived's virtual functions.
   |>     This vtable contains the Derived::f()
   |>
|> |> * Pointer to part of Derived vtable with the same layout as Base vtable.
|> |>     This vtable contains the thunk of Derived::f()
|> |>
|> |> * Data of Base class (variable `x`)
|  |>
|  |> * Data of Derived class (variable `y`)
|  |
|  \ This is complete Derived object.
|    The `d` pointer points at the beginning of this.
|
\ This is the part of Derived object that can act as a Base object.
  The `b` pointer points at beginning of this.

PS:现在应该也清楚为什么打电话了_ZTv0_n24_N7Derived1fEv on the d指针崩溃。该函数仅在给定时才起作用this指向内部的指针Derived对象 - 进入它可以像使用一样的部分Base object.

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

什么是从虚拟基类继承的虚拟函数的“虚拟 thunk”? 的相关文章

  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐

  • 将快捷方式绑定到命令面板命令?

    我刚刚安装了一个名为 CodeSniffer http soulbroken co uk code sublimephpcs 的插件 我想将命令面板中的其中一个命令链接到键盘快捷键 因为我经常使用它 有什么简单的方法可以做到这一点吗 或者我
  • Kendo UI Dropdown,使下拉面板比控件更宽

    在 Kendo UI Dropdown 中 是否可以使下拉面板比控件更宽 另一种可能的方法 var dropdownlist titles data kendoDropDownList set width of the drop down
  • R 中按组的组合

    我有一个关于按组组合的问题 我的迷你样本如下所示 sample lt data frame group c a a a a b b b number c 1 2 3 2 4 5 3 如果我应用以下功能combn对于数据框 它给出了以下结果
  • Flask Web 应用程序的 CSS 问题

    我无法正确输出 CSS 我的网页都是无样式的 这是我所有模板中的链接 我究竟做错了什么 为了让它工作 我需要对 Flask 做些什么特别的事情吗 我已经尝试和改变了大约半个小时 但似乎无法做到正确 总结一下 如何使用 Flask 做 CSS
  • 将“e.target”与 jQuery 对象进行比较

    我想做的事 clickedObject someDiv returns true or false 我尝试过的 e target selector returns a false negative 我的解决方法 e target attr
  • 如何在 BootstrapVue 元素上使用 Vue Test Utils 触发事件?

    这个问题让我很困难 我不明白如何制作Vue 测试工具 and BootstrapVue一起玩得很开心 一个最小的例子如下所示 MyComponent vue
  • Python 日志记录:使用毫秒时间格式

    默认情况下logging Formatter asctime s 使用以下格式打印 2011 06 09 10 54 40 638 其中 638 是毫秒 我需要将逗号更改为点 2011 06 09 10 54 40 638 要格式化时间 我
  • forEach 循环未根据需要更新数组

    我正在尝试循环 consoleOuputParamsOBJ 并更新我的 taskparamscompiled 对象列表中的记录 所需输出 process00x00 i D Code UnitTest ConsoleApp 1 00x00 p
  • 如何检查列是否等于可以为空的变量

    我有一个表 其中包含允许 null 或空值的 varchar 列 我正在编写一个存储过程 其中包含一个可以分配给空值或常规字符串 非空 的变量 它的定义如下 declare myvar varchar 50 现在我正在尝试编写一个查询 该查
  • Rust 中的(嵌套)Vec 是否可以进行模式匹配?

    一个库向我提供了一个我想要匹配的深度嵌套的数据结构 它包含Vec内部 我希望像注释掉的行之一一样起作用 struct Foo bar Vec
  • 带延迟的顺序 Promise 循环

    我正在尝试按顺序加载一组 请求 每个请求之间由延迟分隔 我正在使用承诺 但由于某些原因 我在并行而不是按顺序执行请求时遇到问题 我如下编写了一些测试代码 有用 它发出请求 处理请求 超时 3 秒 然后转到第二个请求 var batches
  • 如何将我的 godaddy 域名链接到 Windows Azure [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我四处搜寻 但仍然找不到任何有关如何执行此操作的信息 理想情况下 我想知道如何链接多个域名 因为我现在使用 SDK 1 3 有人对如何执行此操作有任何
  • 视频上传并在 Django 网站上显示

    我有一个上传视频的模型 我想在浏览器中显示相同的视频 但不知何故我无法做到 请帮助我 我制作了一个名为 部署 的应用程序 我在其中上传视频并保存它 请告诉我哪里做错了以及应该做什么 我希望上传的视频应该显示在页面上 并且应该有一个下载选项
  • 为什么我安装 rmagick 时遇到问题

    在 Ruby 1 8 7 和 Rails 2 3 5 上我得到 gem install rmagick ERROR Error installing rmagick ERROR Failed to build gem native exte
  • SQL语法区分大小写吗?

    SQL 区分大小写吗 我用过MySQL https en wikipedia org wiki MySQL and SQL 服务器 https en wikipedia org wiki Microsoft SQL Server这两者似乎都
  • 什么是 uber JAR 文件?

    我正在阅读 Maven 文档并偶然发现了这个名字uber jar 一个是什么意思uber jar是什么意思以及它的特点 优点是什么 ber德语单词是above or over 它实际上与英语同源over Hence in this cont
  • 如何匹配小于或等于100的数字?

    我想匹配一个小于或等于 100 的数字 它可以是 0 100 之间的任何数字 但正则表达式不应该匹配大于 100 的数字 如 120 130 150 999 等 Try this b 0 1 9 0 9 100 b 解释 b Assert
  • PHP 致命错误:调用未定义的函数 mysqli_stmt_get_result()

    我不断收到错误 PHP Fatal error Call to undefined function mysqli stmt get result 我正在使用 PHP 版本 5 6 并在我的托管提供商 c 面板中启用了扩展 mysqlind
  • XSelectInput 不适用于 ButtonPressEvents,怎么办?

    我正在用 C 语言编写一个简单的程序 我想捕获正在发生的所有鼠标和键盘事件 我尝试使用 XGrabPointer 但它会导致锁定屏幕 并且我无法转到其他应用程序 我尝试使用 XSelectInput 现在我成功接收键盘事件 但没有收到任何鼠
  • 什么是从虚拟基类继承的虚拟函数的“虚拟 thunk”?

    当我尝试访问从虚拟基类继承的派生类对象的内存布局时 出现了问题 编程环境 GNU Linux 3 19 0 32 generic x86 64编译器 gcc 4 8 4 virtual base class class Base publi