问题标签 [vtable]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
1318 浏览

c++ - 如何使用 vtable 确定类类型

我最近接受了一个 C/C++ 是主要语言的职位的面试,在一个问题中,我被告知可以使用 vtable 来确定基指针实际存储的层次结构中的哪个类。

因此,例如,如果您有

然后实例化A * pFoo = new B(),是否确实可以使用 vtable 来确定 pFoo 是否包含指向 A 或 B 实例的指针?

0 投票
2 回答
2139 浏览

c++ - 转储类层次结构的 Visual C++ 编译器选项

MS Visual C++ 中是否有任何与 GCC 的 -fdump-class-hierarchy 等效的编译器选项?即显示虚函数表布局。

0 投票
4 回答
463 浏览

c++ - 获取所有现有 vtable 的列表

在我的应用程序中,我有很多空指针(这是由于历史原因,应用程序最初是用纯 C 编写的)。在我的一个模块中,我知道 void-pointers 指向可以从已知基类继承的类的实例,但我不能 100% 确定这一点。因此,对 void 指针执行 dynamic_cast 可能会出现问题。可能,void 指针甚至指向一个普通结构(因此结构中没有 vptr)。

我想调查 void-pointer 指向的内存的前 4 个字节,看看这是否是有效 vtable 的地址。我知道这是平台,甚至可能是特定于编译器版本的,但它可以帮助我推动应用程序向前发展,并在有限的时间段内(比如说 3 年)摆脱所有空指针。

有没有办法获取应用程序中所有 vtable 的列表,或者检查指针是否指向有效的 vtable,以及指向 vtable 的实例是否继承自已知的基类?

0 投票
2 回答
4920 浏览

java - 是什么导致“java.lang.IncompatibleClassChangeError: vtable stub”?

是什么导致“java.lang.IncompatibleClassChangeError: vtable stub”?在我们的应用程序中,我们看到这个错误随机弹出并且非常少见(到目前为止只有两次,而且我们经常运行它)。即使重新启动应用程序,使用相同的 jvm/jars 而不重新构建,它也不容易重现。

至于我们的构建过程,我们清理所有类/jar并重建它们,所以这与其他人遇到的问题不同,他们在一个类中进行了更改并且没有重新编译其他一些依赖类。

这与其他一些与 IncompatibleClassChangeError 相关的问题不同——它们都没有提到“vtable stub”。事实上,在搜索“IncompatibleClassChangeError "vtable stub"”时,谷歌搜索结果出奇地少。

编辑:

  • 使用 JDK 1.6.0_16。
  • 我们没有使用 Java 序列化。
  • 我们不是在做字节码操作。
  • 如前所述,我们正在进行“干净的构建”,因此之前的构建没有遗留任何类。
0 投票
5 回答
14641 浏览

c++ - 虚拟成员函数的打印地址

我正在尝试打印虚拟成员函数的地址。如果我知道哪个类实现了我可以编写的函数:

但我想做这样的事情:

但是,这不会编译。是否有可能做这样的事情,也许在运行时在 vtable 中查找地址?

0 投票
3 回答
2369 浏览

c++ - 使用虚拟继承解析 C++ vtable

我对 C++ 和虚拟继承很好奇——尤其是在 bass 和子类之间解决 vtable 冲突的方式。我不会假装理解它们如何工作的细节,但到目前为止我所看到的是它们是由于该分辨率而使用虚函数引起的一个小延迟。那么我的问题是,如果基类是空白的 - 即它的虚函数定义为:

这是否意味着不需要分辨率,因为只有一组函数可供选择?

如果这是一个愚蠢的问题,请原谅我——正如我所说,我不明白 vtables 是如何工作的,所以我真的不知道更好。

编辑

因此,如果我有一个带有两个单独子类的抽象类:

从子类调用函数时没有性能损失,而不是说,只是一个单继承自由类?

0 投票
4 回答
1292 浏览

delphi - Delphi 中的 COM 方法偏移量

在 Delphi 中,如何找出 COM 方法的地址?我可以硬编码偏移量

但我更喜欢使用符号名称。以下显然不起作用:

谢谢!

0 投票
4 回答
915 浏览

c++ - c++ 虚拟调用 w/ vtable 实现中的多线程竞争条件的怀疑

我怀疑在某些 C++ 多线程情况下可能存在竞争条件,涉及 vtable 动态调度实现中的虚拟方法调用(为此,vtable 指针作为隐藏成员存储在具有虚拟方法的对象中)。我想确认这是否真的是一个问题,并且我指定了 boost 的线程库,以便我们可以假设一些参考框架。

假设一个对象“O”有一个 boost::mutex 成员,它的整个构造函数/析构函数和方法都被范围锁定(类似于 Monitor 并发模式)。线程“A”在没有外部同步的情况下在堆上构造对象“O”(即没有包含“新”操作的共享互斥锁,它可以与其他线程同步;但请注意,仍然存在“内部,Monitor”互斥锁其构造函数的作用域)。然后,线程 A 通过同步机制将指向“O”实例(它刚刚构建)的指针传递给另一个线程“B”——例如,同步的读写器队列(注意:只有指向对象正在被传递——而不是对象本身)。施工后,

线程“B”从同步队列中读取对象“O”的指针值,然后立即离开保护队列的临界区。然后线程“B”对对象“O”执行虚方法调用。这是我认为可能出现问题的地方。

现在,我对动态调度的[很可能的] vtable 实现中的虚拟方法调用的理解是,调用线程“B”必须取消引用指向“O”的指针,以便获得存储为其对象的隐藏成员的 vtable 指针,并且这发生在进入方法体之前(自然是因为在访问存储在对象本身中的 vtable 指针之前,要执行的方法体不能安全准确地确定)。假设上述陈述对于这样的实现可能是正确的,这不是竞争条件吗?

由于在任何内存可见性保证操作发生之前(即获取对象“O”中的成员变量mutex),线程“B”(通过解除指向位于堆中的对象“O”的指针)检索vtable指针,那么不确定“B”会感知“A”最初写在对象“O”的构造上的vtable指针值,对吗?(即,它可能会感知到垃圾值,从而导致未定义的行为,对吗?)。

如果上述是有效的可能性,这是否意味着对线程之间共享的专有内部同步对象进行虚拟方法调用是未定义的行为?

而且——同样——由于标准对 vtable 实现是不可知的,如何保证 vtable 指针在虚拟调用之前对其他线程安全可见?我想人们可以在外部同步(“外部”,例如,“围绕共享互斥锁()/解锁()块”)构造函数调用,然后至少在每个线程中进行初始虚拟方法调用,但这似乎是一些非常不和谐的编程。

所以,如果我的怀疑是真的,那么一个可能更优雅的解决方案是使用内联的非虚拟成员函数来锁定成员互斥体,然后转发到虚拟调用。但是——即使那样——我们能否保证构造函数在 lock() 和 unlock() 的范围内初始化了 vtable 指针来保护构造函数本身?

如果有人可以帮助我澄清这一点并确认/否认我的怀疑,我将不胜感激。

编辑:演示以上内容的代码

-- 在第 (4) 点,我的印象是“线程 A”写入内存的 vtable 指针值可能对“线程 B”不可见,因为我看不出有任何理由假设编译器会生成代码,以便将 vtable 指针写入构造函数的锁定互斥块中。

例如,考虑多核系统的情况,其中每个内核都有一个专用缓存。根据这篇文章,缓存通常是积极优化的,并且——尽管强制缓存一致性——如果不涉及同步原语,则不会对缓存一致性强制执行严格的排序。

也许我误解了这篇文章的含义,但这并不意味着“A”将 vtable 指针写入构造对象(并且没有迹象表明这种写入发生在构造函数的锁定互斥块中)可能在“B”读取 vtable 指针之前不会被“B”感知?如果 A 和 B 都在不同的内核上执行(“A”在 core0 上,“B”在 core1 上),缓存一致性机制可能会重新排序 core1 缓存中 vtable 指针值的更新(使其一致的更新与 core0 的缓存中的 vtable 指针的值,“A”写)这样它发生在“B”的读取之后......如果我正确解释了这篇文章。

0 投票
3 回答
503 浏览

c++ - C++ 中的继承成本

以下面的代码片段为例:

如您所见,这种关系中不存在虚函数。既然是这种情况,就语言而言,以下假设是否准确?

  • 不会创建虚函数表Bar
  • sizeof(Bar) == sizeof(Baz)

基本上,我想弄清楚我是否会为此付出任何惩罚。我的初始测试(尽管在单个编译器上)表明我的断言是有效的,但我不确定这是我的编译器的优化器还是负责我所看到的内容的语言规范。

0 投票
4 回答
1552 浏览

visual-c++ - vtable 中重载方法的顺序(在 win32 上)

vtable 中重载方法的顺序在 win32 编译器中是否始终相同?

问题:我有“接口”(没有数据成员的纯虚拟类)。它们可以通过来自不同编译器的指针来使用(客户端通过调用标准的 c dll 工厂方法获取指针)。除了一种方法外,这在不同的编译器(例如,用 borland 编写的客户端、用 Visual C++ 编写的接口 dll)上都可以正常工作。该方法重载了相同的返回值但不同的参数。此方法有 4 个版本。根据编译客户端的编译器,对该方法的相同调用会返回不同的结果。快速浏览一下汇编代码,我发现 vtable 中似乎有不同的偏移量(我不太擅长阅读汇编程序)。

现在我不知道 - 我是否找到了原因,或者是 borland 只是处理与 Visual Studio 不同的 vtable,一切都是正确的,我必须在其他地方搜索。

最好的问候,谢谢你的回答

托拜厄斯