I wish to use a small program to detect the feature of vtable. I know for most popular compilers, they'll generate objects with leading size_t of its head to be a pointer to vtable. So I tried to convert this pointer and use it for a direct function call.
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;
}
I wish that (*func1)() will print out "weird". But the actural result was core dump.
Where did I get wrong in my program? Thanks.
Update:
You have a mistake here:
pf* pvtable=(pf*)p;
You are casting the pointer to object C
to a pointer to vtable. Therefore you are interpreting the content of the C
object as a vtable. Instead you need to go one indirection further; cast the pointer to C
to a pointer-to-pointer to vtable and dereference it:
pf* pvtable=*(pf**)p;
This way you will follow the pointer stored at the beginning of C
object to the actual vtable.
My original answer that is rewriten more:
#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;
}
This will work at least with gcc and clang on Linux, possible with other compilers too. But it is implementation dependent!