动态分配对象调用虚方法Core Dump:为何main中正常函数调用时崩溃?
虚函数调用崩溃问题分析
问题背景
以下代码中,main()里直接调用c->b.f()能正常输出"B",但将c->b传入fun()函数后调用b.f()会触发Core Dump,具体原因如下:
class A { public: inline virtual void f() const {printf("A\n");} }; class B : public A { public: inline void f() const override {printf("B\n");} }; class C { public: B b; }; void fun(const B &b) { b.f(); // coredump } int main() { C *c = (C*)malloc(sizeof(C)); c->b.f(); // print "B" fun(c->b); return 0; }
核心原因
malloc不执行构造函数:malloc仅负责分配内存空间,不会调用类的构造函数。对于带虚函数的类(比如继承了A的B),构造函数的关键作用是初始化虚表指针(vptr),让它指向类对应的虚表(vtable)。用malloc创建的对象,vptr是内存里的随机垃圾值。直接对象调用的静态绑定优化:
main()中c->b.f()是直接通过对象实例调用虚函数,且f()是inline函数。编译器会做去虚拟化优化,直接编译为静态调用B::f(),完全不需要访问虚表,因此哪怕vptr未初始化,也能正常执行。引用调用的动态绑定要求:当把
c->b传给fun()的const B&参数时,函数内的b.f()是通过引用调用虚函数。C++规定,通过指针/引用调用虚函数必须走动态绑定:通过对象的vptr找到虚表,再定位到目标函数地址。此时vptr是未初始化的垃圾值,访问该地址会触发非法内存访问,直接导致Core Dump。
解决方法
改用new创建C对象,new会自动调用C及成员B的构造函数,正确初始化虚表指针:
int main() { C *c = new C(); c->b.f(); fun(c->b); delete c; return 0; }
内容的提问来源于stack exchange,提问作者brayden
相关产品推荐
相关产品推荐

