如何修复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
相关产品推荐
相关产品推荐

