【问题标题】:C++: How to look at vptr/ vtable contentsC++:如何查看 vptr/vtable 内容
【发布时间】:2014-11-28 04:54:31
【问题描述】:

每个具有虚函数的 C++ 对象都有一个指向 vtable 的 vptr。我怎样才能看到这个 vptr 是什么,以及它指向的内容?我知道这取决于编译器,它可以将 vptr 放在对象内存空间的任何位置。但是有没有我能找到它是什么?

干杯。

【问题讨论】:

  • 你为什么要这样做?
  • “每个具有虚函数的 C++ 对象都有一个指向 vtable 的 vptr。” - C++ 标准本身并没有规定应该如何编排虚拟调度,所以这是真的 - 据我所知 - 所有当前可用的 C++ 编译器和可能仍然如此,但不确定,尤其是在例如在一个翻译单元中编译的更简单的程序,实际上并没有在运行时使用虚拟调度或 RTTI。
  • 谢谢。我知道如果程序不需要动态绑定,一些编译器会选择不进行动态绑定。但我的需要是当 vtpr/vtable 存在时如何查看这个指针是什么并查看它的内容。
  • 这是我的另一个书签,您可能会喜欢 - 它解释了 VDT 和 RTTI 信息的一种布局标准:Itanium C++ ABI。如果你想“看看这个指针是什么”等。在 gdb 或你使用的任何调试器中四处寻找......

标签: c++ vtable vptr


【解决方案1】:

在这种特定情况下,C 有一个 vtable,而 A 和 B 没有。您可以通过外联 C 的成员函数自己看到这一点,以便实际发出 vtable,并更正其他编译错误: extern "C" int puts(const char *);

struct A { virtual void func_1() = 0; };
struct B { virtual void func_2() = 0; };

struct C : A, B
{
  void func_1();
  void func_2();
};

...编译成目标文件,然后查看符号:

$ gcc -c test.cc
$ nm test.o | c++filt
                 U puts
0000000000000000 T C::func_1()
000000000000001a T C::func_2()
0000000000000033 T non-virtual thunk to C::func_2()
0000000000000000 V typeinfo for A
0000000000000000 V typeinfo for B
0000000000000000 V typeinfo for C
0000000000000000 V typeinfo name for A
0000000000000000 V typeinfo name for B
0000000000000000 V typeinfo name for C
0000000000000000 V vtable for C
                 U vtable for __cxxabiv1::__class_type_info
                 U vtable for __cxxabiv1::__vmi_class_type_info
    void C::func_1() { puts("func_1"); }
    void C::func_2() { puts("func_2"); }

通过以上步骤可以找到它所指向的内容。

【讨论】:

  • 这里实际上有两个vtable:一个用于A,一个用于B。