我正在学习 C++ 类的对象模型,我在 ubuntu g++11 中做了如下演示:
#include <iostream>
using namespace std;
class B {
public:
B(int i = 1) : ib(i) {}
virtual void f() { printf("B::f()\n"); }
virtual void Bf() { printf("B::Bf()\n"); }
private:
int ib;
};
class B1 : virtual public B {
public:
B1(int i = 100) : ib1(i) {}
virtual void f() { printf("B1::f()\n"); }
virtual void f1() { printf("B1::f1()\n"); }
virtual void Bf1() { printf("B1::Bf1()\n"); }
private:
int ib1;
};
using fn = void(*)(void);
int main() {
B1 b1;
size_t* vptr = *(size_t**)(&b1);
size_t thunkAddr = vptr[7];
fn thunkFunc = (fn)(thunkAddr);
thunkFunc();
// ((fn)(thunkAddr))(); <-- error occured: Segmentation fault (core dumped)
return 0;
}
更重要的是,下面的代码也让我感到困惑:
int main() {
B1 b1;
size_t* vptr = *(size_t**)(&b1);
printf("vb_offset : %ld\n", *(vptr - 3));
printf("top_offset : %ld\n", *(vptr - 2));
type_info* info = (type_info*)(*(vptr - 1));
printf("typeinfo : [name:%s, hash:%lx]\n", info->name(), info->hash_code());
printf("call B1::f : "); ((fn)(*(vptr + 0)))();
printf("call B1::f1 : "); ((fn)(*(vptr + 1)))();
printf("call B1::Bf1: "); ((fn)(*(vptr + 2)))();
printf("padding : %ld\n", *(vptr + 3));
printf("vb_offset : %ld\n", *(vptr + 4));
printf("top_offset : %ld\n", *(vptr + 5));
info = (type_info*)(*(vptr + 6));
printf("typeinfo : [name:%s, hash:%lx]\n", info->name(), info->hash_code());
// printf("B1::f[thunk]: "); fn thunk = (fn)(vptr[7]); thunk(); <-- Segmentation fault (core dumped)
printf("call B::Bf : "); ((fn)(*(vptr + 8)))();
printf("--------------------------------------\n");
printf("vptr from B : %p\n", vptr + 7);
printf("vptr from B : %p\n", ((size_t**)(&b1))[2]);
return 0;
}
但是当我使用“g++ -O test.cpp”而不是“g++ test.cpp”编译代码时,所有错误都消失了。
有人可以回答我的问题吗?非常感谢。
我使用了不同的方法来调用thunkfunc,下面的方法可以正常工作:
fn thunkFunc = (fn)(thunkAddr);
thunkFunc();
但另一种方法不起作用:
((fn)(thunkAddr))();