我希望使用一个小程序来检测vtable的功能。我知道对于大多数流行的编译器来说,它们将生成对象,其头的size_t领先于vtable。因此,我尝试转换此指针并将其用于直接函数调用。
typedef void (*pf)();
struct C
{
virtual void f(){
printf("weird\n");
}
};
int main()
{
C c1;
C* p=&c1;
pf* pvtable=(pf*)p;
pf func1=pvtable[0];
(*func1)();
return 0;
}
我希望(* func1)()将打印出“怪异”的字样。但实际结果是核心转储。
我的程序在哪里出错?
谢谢。
最佳答案
更新:
您在这里有一个错误:
pf* pvtable=(pf*)p;
您正在将对象
C
的指针转换为vtable的指针。因此,您正在将C
对象的内容解释为vtable。相反,您需要进一步进行间接操作。将指向C
的指针强制转换为指向vtable的指针并取消引用:pf* pvtable=*(pf**)p;
这样,您将遵循存储在
C
对象开头的指针到实际vtable。我的原始答案被重写为:
#include <iostream>
struct C
{
virtual void f()
{
std::cout << "weird" << std::endl;
}
};
typedef void** C_vtable;
typedef void (C_f)(C* thiz);
int main()
{
// Create the object on stack
C c1;
// Reinterpret its address to an address of a virtual table and dereference it.
C_vtable vtable = *reinterpret_cast<C_vtable*>(&c1);
// Pick the first pointer from the virtual table and reinterpret it as our function
C_f *func1 = reinterpret_cast<C_f*>(vtable[0]);
// Call it
(*func1)(&c1);
return 0;
}
这至少可以在Linux上的gcc和clang上运行,其他编译器也可以。但这取决于实现!
关于c++ - 我试图访问C++多态类的vtable,但由于核心转储而失败,为什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39469150/