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

C++多继承下delete Base2指针报free错误的原因及修复方法

错误原因

  • 多继承的对象布局问题:派生类B同时继承Base1、Base2两个基类,编译器会按继承声明顺序在B的内存布局开头依次放置两个基类的子对象:第一个是Base1子对象,第二个是Base2子对象。
    • 当你把new B返回的B*指针赋值给Base1*时,指针指向的地址刚好和B对象的起始地址一致,delete x时传给free的地址和new分配的地址匹配,所以碰巧没有报错。
    • 当你把B*指针赋值给Base2*时,编译器会自动做地址偏移,让指针指向B对象内部的Base2子对象的起始地址,这个地址和new B返回的原始分配地址不一致。
  • 核心诱因是基类没有声明虚析构函数:当基类没有虚析构函数时,delete 基类指针执行的是静态类型匹配,会直接把当前基类指针的地址传给free,而不会先调整回派生类对象的原始起始地址,最终传给free的是偏移后的非法地址,就触发了free(): invalid pointer错误。

注意:哪怕使用Base1指针时程序没有崩溃,这也是未定义行为,只是刚好地址匹配才没有触发错误,不代表代码本身是正确的。

修复方法

只需要给所有用作基类的类添加虚析构函数即可,修改后的基类代码如下:

class Base1 {
public:
    virtual void method1() = 0;
    virtual ~Base1() = default; // 添加虚析构
};

class Base2 {
public:
    virtual void method2() = 0;
    virtual ~Base2() = default; // 添加虚析构
};

添加虚析构后,delete 基类指针时会先通过虚表找到派生类的析构函数,自动把指针调整回派生类对象的原始起始地址再释放内存,就不会出现地址不匹配的问题。

内容的提问来源于stack exchange,提问作者Andrea

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:18:03