You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用抽象类析构函数后,访问重写纯虚函数触发调试终止错误

手动调用抽象类析构函数后调用纯虚函数触发崩溃的原因及修复
#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:42:36