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

从C++ vector中删除含堆内存的自定义类对象时出现double free错误

错误原因

你的问题核心是自定义类违反了C++的三五法则,默认拷贝行为是浅拷贝,触发了重复释放内存的问题,具体逻辑如下:

  • 你没有为类B显式实现拷贝构造函数、拷贝赋值运算符,编译器会自动生成默认实现,默认实现只会逐字节复制对象的成员值:也就是会直接复制hehe指针本身的地址,不会为新对象申请独立的堆内存,这就是浅拷贝。
  • 当你对存储了5个B对象的vector执行erase删除下标2的元素时,vector会把下标3、4的元素向前移动到下标2、3的位置,移动过程会调用默认拷贝赋值运算符:
    1. 下标3的对象赋值给下标2的位置后,两个对象的hehe指针指向同一块堆内存
    2. 移动完成后,原来下标4的对象会被析构,释放它的hehe指向的内存,这时新的下标3的对象的hehe已经变成野指针
    3. 后续整个vector销毁、逐个析构元素时,野指针会被再次delete,就触发了double free错误。

为什么元素数为1时运行正常

当vector里只有1个元素,执行erase时不需要移动其他元素,直接析构这唯一的对象即可,全程不会触发浅拷贝,也就不会出现多个对象共享同一块堆内存的情况,所以不会报错。

解决方法

你可以选择以下任意一种方案修复问题:

方案1:显式实现深拷贝逻辑,符合三五法则

为类B补充实现拷贝构造、拷贝赋值运算符,保证每个对象的hehe指针指向独立的堆内存:

class B
{
public:
    std::string a;
    std::string b;
    int *hehe;

    B()
    {
        a = "Hello";
        b = ", World!";
        hehe = new int[7];
        for (int i = 0; i < 7; ++i) {
            hehe[i] = i;
        }
    }

    // 拷贝构造
    B(const B& other) {
        a = other.a;
        b = other.b;
        hehe = new int[7];
        for (int i = 0; i <7; ++i) {
            hehe[i] = other.hehe[i];
        }
    }

    // 拷贝赋值运算符
    B& operator=(const B& other) {
        if (this == &other) return *this;
        // 释放原有内存
        delete[] hehe;
        // 深拷贝新内容
        a = other.a;
        b = other.b;
        hehe = new int[7];
        for (int i = 0; i <7; ++i) {
            hehe[i] = other.hehe[i];
        }
        return *this;
    }

    ~B() {
        if (hehe)
            delete[] hehe;
    }
};

方案2:使用标准容器/智能指针代替裸指针,避免手动管理内存

这是更推荐的方案,不用手动管理内存,编译器默认生成的拷贝行为就符合预期:

#include <vector>
class B
{
public:
    std::string a;
    std::string b;
    // 用std::vector代替裸数组,无需手动申请释放内存
    std::vector<int> hehe;

    B()
    {
        a = "Hello";
        b = ", World!";
        hehe.resize(7);
        for (int i = 0; i < 7; ++i) {
            hehe[i] = i;
        }
    }
    // 不需要手动实现析构、拷贝构造、拷贝赋值,默认实现即可正常工作
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:24:02