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

如何修复C++运行时报错"free(): double free detected in tcache 2"

问题根因
  • 派生类重复定义基类成员引发同名隐藏:基类arrayListType已经定义了list(存储数组的指针)、length、maxSize三个核心成员,派生类unorderedSet又额外定义了set、length、maxSize,导致派生类中操作的成员和基类操作的成员是完全独立的两套数据,状态完全不一致。你之前自行重写赋值运算符时输出为空,正是因为你只操作了派生类的set相关成员,而业务数据实际存储在基类的list中,两者数据不互通。
  • 资源管理混乱:派生类自己申请了set指向的堆内存,但所有集合操作(比如insertEnd、运算符重载里的元素读取)实际操作的是基类的list数组,set指向的内存完全未被使用,还会在析构时触发非法释放。
  • 赋值运算符不匹配:基类的赋值运算符只会处理基类自己的list、length、maxSize成员,不会处理派生类新增的set等成员,赋值后派生类的set是野指针,析构时直接触发段错误(核心转储)。
  • 拷贝构造函数未调用基类构造:派生类自定义的拷贝构造没有调用基类的拷贝构造,基类的list等成员未被正确初始化,处于野指针状态。
修复方案
  • 删除派生类中重复定义的冗余成员:删掉unorderedSet类定义里的elemType *set;、int length;、int maxSize三个成员,直接复用基类的同名成员即可。
  • 清理派生类中冗余的资源管理代码:删掉析构函数里的delete [] set;逻辑,删掉构造函数里的set = new elemType[this->maxSize];相关逻辑,删掉拷贝构造函数里的set数组拷贝逻辑,堆内存的申请、释放完全交给基类处理。
  • 补全派生类的拷贝构造和赋值运算符:拷贝构造显式调用基类的拷贝构造,赋值运算符先调用基类的赋值运算符完成基类成员的拷贝。
  • 修复原有构造函数的缩进问题:原来的else分支缺少大括号,导致length初始化、内存申请逻辑无论参数是否合法都会执行,冗余成员删除后该问题同步解决。
关键修复后代码示例
template <class elemType>
class unorderedSet: public unorderedArrayListType<elemType>
{
public:
  void insertAt(int location, const elemType& insertItem);
  void insertEnd(const elemType& insertItem);
  void replaceAt(int location, const elemType& repItem);
  const unorderedSet<elemType> operator+(const unorderedSet<elemType>&);
  const unorderedSet<elemType> operator-(const unorderedSet<elemType>&);
  
  unorderedSet(int size = 100);
  unorderedSet(const unorderedSet<elemType>& otherSet);
  // 派生类无新增资源,不需要自定义析构函数,用默认析构即可
  const unorderedSet<elemType>& operator=(const unorderedSet<elemType>& otherSet);
};

// 构造函数
template <class elemType>
unorderedSet<elemType>::unorderedSet(int size) : unorderedArrayListType<elemType>(size)
{
  // 大小合法性校验建议移到基类实现,若基类未做可在此处调整基类的maxSize、length
}

// 拷贝构造函数
template <class elemType>
unorderedSet<elemType>::unorderedSet(const unorderedSet<elemType>& otherSet) 
  : unorderedArrayListType<elemType>(otherSet)
{
  // 基类已经完成所有成员的拷贝,无需额外操作
}

// 赋值运算符重载
template <class elemType>
const unorderedSet<elemType>& unorderedSet<elemType>::operator=(const unorderedSet<elemType>& otherSet)
{
  if (this != &otherSet)
  {
    // 调用基类赋值运算符完成基类成员拷贝
    unorderedArrayListType<elemType>::operator=(otherSet);
  }
  return *this;
}

// operator+逻辑保持不变即可,操作的都是基类继承来的list、length成员
template <class elemType>
const unorderedSet<elemType> unorderedSet<elemType>::operator+(const unorderedSet<elemType>& otherSet)
{
  unorderedSet<elemType> unSet(this->length + otherSet.length);
  for (int i = 0; i < this->length; i++)
    unSet.insertEnd(this->list[i]);
  for (int i = 0; i < otherSet.length; i++)
    unSet.insertEnd(otherSet.list[i]);
  return unSet;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 18:36:05