我希望使用一个小程序来检测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/

10-13 08:18