C++自定义String类运行报pointer being freed was not allocated错误求解
问题排查与修复
核心错误原因
- 未显式实现拷贝赋值运算符
operator=:C++类如果没有自定义拷贝赋值运算符,编译器会自动生成默认的浅拷贝版本。执行string1 = s1这类赋值操作时,只会直接复制str指针的地址,不会重新分配内存拷贝字符串内容,导致两个对象的str成员指向同一块堆内存。两个对象生命周期结束调用析构函数时,同一块内存会被重复释放,触发malloc报错。 - 补充隐患:默认构造函数中
str为NULL,如果直接对默认构造的未赋值对象执行cout输出,会触发未定义行为;另外当前operator<=的实现是比较字符串长度而非字典序,不符合常规字符串比较逻辑,可按需调整。
修复方案
第一步:新增拷贝赋值运算符声明
在String类的public成员中添加operator=的声明:
class String { char *str; int len; public: String(); String(const char*); String(const String&); ~String(); // 新增拷贝赋值运算符声明 String& operator=(const String&); friend String operator + (const String&, const String&); friend bool operator <= (const String&, const String&); friend ostream& operator << (ostream&, const String&); };
第二步:实现深拷贝的赋值运算符
String& String::operator=(const String& str1) { // 防止自赋值 if(this == &str1) return *this; // 释放当前对象原有堆内存 delete[] str; // 分配新内存并拷贝内容 len = str1.len; str = new char[len + 1]; strcpy(str, str1.str); return *this; }
可选优化
如果要规避空对象输出的未定义行为,可以调整默认构造函数,给空字符串分配1字节存储结束符:
String::String(void) { len = 0; str = new char[1]; str[0] = '\0'; }
如果需要operator<=符合常规字符串字典序比较逻辑,修改实现如下:
bool operator <= (const String& str1, const String& str2) { return strcmp(str1.str, str2.str) <= 0; }
验证
修改完成后重新编译运行,输出结果正常,不会再触发内存报错:
New York NewDelhi
内容的提问来源于stack exchange,提问作者Ratnadip Das
相关产品推荐
相关产品推荐

