调用抽象类析构函数后,访问重写纯虚函数触发调试终止错误
手动调用抽象类析构函数后调用纯虚函数触发崩溃的原因及修复
#include <iostream> using namespace std; class Abstract { protected: int* arr; int size; public: Abstract(int s = 10) { size = s; arr = new int[size]; } virtual ~Abstract() { if (arr) { delete[] arr; } arr = nullptr; } virtual void foo() = 0; void func() { foo(); } }; class Derived : public Abstract { public: void newArr() { Abstract::~Abstract(); // <=> this->~Derived() arr = new int[size]; } virtual void foo()override {}; }; int main() { Derived d; d.func();//ok d.newArr();//ok d.func();//error return 0; }
问题分析
这段代码中,调用Derived::newArr()时手动触发Abstract的析构函数,后续调用func()触发纯虚函数foo()时,程序直接触发debug abort()错误,无法正确调用Derived中重写的foo()实现,原因如下:
- 析构函数是虚函数,手动调用
Abstract::~Abstract()会触发完整的析构链:先调用Derived的默认析构函数,再执行Abstract的析构逻辑。 - 对象析构过程中,虚函数表会逐步切换为基类的虚表,析构完成后,对象的生命周期已经终结,其虚表指针指向
Abstract的虚表。 - 后续重新分配
arr内存的操作,无法恢复对象的虚表状态,此时调用func()中的foo(),会尝试调用Abstract的纯虚函数(无实现),直接触发程序abort。
修复方案
无需手动调用析构函数,直接释放旧内存并重新分配即可——当前对象仍处于活跃生命周期,手动调用析构会提前终结对象有效性。修改后的newArr()函数如下:
void newArr() { delete[] arr; // 直接释放旧内存 arr = new int[size]; }
内容的提问来源于stack exchange,提问作者Benny
相关产品推荐
相关产品推荐

