【问题标题】:how to lookup c++ virtual table?如何查找 C++ 虚拟表?
【发布时间】:2021-03-11 02:52:47
【问题描述】:

一个简单的示例代码如下:

#include <iostream>

class Base
{
public:
    virtual void func0() { std::cout << "Base::func0" << std::endl; };
    virtual void func1() { std::cout << "Base::func1" << std::endl; };
};


int main()
{
    auto instance = Base();
    uint64_t* vtableAddr = reinterpret_cast<uint64_t*>(&instance);
    uint64_t* pVtable = reinterpret_cast<uint64_t*>(*vtableAddr);
    auto func0 = reinterpret_cast<void(*)(Base*)>(*(pVtable + 0));
    auto func1 = reinterpret_cast<void(*)(Base*)>(*(pVtable + 1));
    func0(&instance);
    func1(&instance);

    auto func2 = reinterpret_cast<void(*)(Base*)>(*(pVtable + 2)); // exceed the limitation
    func2(&instance); // core dump
}

我可以通过首先读取 8 个字节(64 位编译器)的类来获取虚拟表地址。但我不知道是否有办法在运行时获得 pVtable 的最大合法偏移量。
如上例,如果我将pVtable的偏移量设置为2,并调用转换后的函数,会导致coredump。
每个类的虚拟表“大小”是否存储在哪里?

【问题讨论】:

  • vtable 是一种可能的实现,但不是必需的实现......您所做的似乎是运行时意外/错误的秘诀。建议考虑使用成员函数指针
  • 这是一项学术练习,还是您要解决的具体问题?
  • 一个有趣的练习:试着计算这段代码中有多少未定义行为的实例。
  • 无法保证 vtable 存在,一旦您处理更复杂的继承(多重/虚拟和多重/虚拟的组合),您将会非常失望。
  • 编译器在运行时不需要知道 vtable 的限制,因为它在编译时具有类的完整定义(包括 vtable 大小)。它不会生成超出这些限制的代码。不过,这并不能阻止你做一些愚蠢的事情。

标签: c++ vtable


【解决方案1】:

无法保证 vtable 存在,一旦您处理更复杂的继承(多重/虚拟和多重/虚拟的组合),您将会非常失望。来自@Stephen Newell

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    相关资源
    最近更新 更多