c++ 使用函数指针结构体改变类的虚函数表

文中代码 如果c++的类有虚函数那么这个类的实例对象就会有一个虚表. 我们可以通过一下代码来 改变虚表. #include <cstring> #include <iostream> class A { public: virtual void vfoo_1() { std::cout << "a_vfoo_1\n"; } virtual void vfoo_2(long long a) { std::cout << "a_vfoo_2: " << a << std::endl; } virtual int vfoo_3(int a, int b) { return a + b; } }; typedef void (*void_pfunc_void)(); typedef void (*void_pfunc_int)(long long); typedef int (*int_pfunc_int_int)(int, int); struct other_vtable { void_pfunc_void pf1; void_pfunc_int pf2; int_pfunc_int_int pf3; }; void g_f1() { std::cout << "g_f1\n"; } void g_f2(long long a) { ((A *)a)->vfoo_1(); printf("%p\n", (void *)a); // std::cout << "g_f2: " << a << std::endl; } int g_f3(int a, int b) { return b * 10; } int main(void) { A *a = new A; other_vtable *ovt = new other_vtable; ovt->pf1 = g_f1; ovt->pf2 = g_f2; ovt->pf3 = g_f3; void *ptr = a; printf("%p\n", a); a->vfoo_1(); a->vfoo_2(10); printf("a->vfoo_3: %d\n", a->vfoo_3(2, 5)); puts("-------------------------------"); memcpy(ptr, &ovt, sizeof(void *)); a->vfoo_1(); a->vfoo_2(10); printf("a->vfoo_3: %d\n", a->vfoo_3(2, 5)); int breakpoint = 0; return 0; } 内存布局大致如下图所示: ...

使用 gdb 查看 c++ 中的虚函数表

文中代码 1. 使用info vtbl obj查看vtable vtable function class A { public: A() = default; ~A() = default; virtual void vfoo_1() {} virtual void vfoo_2() {} }; int main(void) { A *a = new A; int breakpoint = 0; return 0; } 当一个class有virtual function时, 这个类会有一个vtable(virtual table)来记录这些函数的入口. 编译上面的代码, 使用gdb来debug这个程序, 使用info vtbl a可以可视化该实例对象a的vtable. 如下图所示: vtable class // A // / \ // / \ // B C // \ / // \ / // D class A { public: ~A() = default; virtual void a_foo() {} }; class B : virtual public A { public: virtual void b_foo() {} }; class C : virtual public A { public: virtual void c_foo() {} }; class D : public B, public C { public: }; int main(void) { D *d = new D; int breakpoint = 0; return 0; } 同样使用info vtbl d可以查看实例对象d的vtable. 如下图所示: ...