自定义C++ String类报错:待释放指针未分配,求解决方案
首先,你遇到的malloc错误本质是野指针被非法释放。让我们一步步拆解问题和解决方案:
错误根源
当你调用默认构造函数String s1;时,构造函数会调用initialize(),但此时charArr作为类的非静态成员变量,在C++98/03中没有显式初始化的话,会持有随机垃圾值(不是你以为的0或nullptr)。这就导致if(charArr != 0)的条件意外成立,代码尝试delete[]一个从未被new分配过的野指针,触发了内存错误。
另外,析构函数调用initialize()也是不合理的——initialize()是用来重置对象状态的,析构函数只需要完成自身资源的清理即可。
分步解决方案
1. 用构造函数初始化列表避免野指针
因为你不能使用C++11的类内初始化特性,我们可以在每个构造函数的初始化列表里显式初始化len和charArr,确保对象创建时成员变量处于安全状态:
// String.cpp 中修改构造函数: String::String() : len(0), charArr(nullptr) { // 初始化列表已经完成了基础初始化,无需调用initialize() } String::String(const char *arr) : len(0), charArr(nullptr) { copyString(arr); } String::String(const String& arr) : len(0), charArr(nullptr) { copyString(arr.charArr); }
2. 修正initialize()的职责与逻辑
initialize()的定位应该是重置对象的现有状态(比如清空已有的字符串),而不是初始化新对象。我们要确保只在charArr确实指向已分配内存时才释放:
void String::initialize(){ if(charArr != nullptr){ delete [] charArr; charArr = nullptr; // 释放后置空,避免悬空指针 } len = 0; }
3. 修复析构函数的错误调用
析构函数只需要负责清理当前对象的资源,不需要调用initialize(),直接释放charArr即可:
String::~String(){ delete [] charArr; charArr = nullptr; // 可选,但这是避免悬空指针的好习惯 }
4. 完善copyString()的安全性
现在charArr已经在构造时初始化为nullptr,copyString()里的判断逻辑会更安全,同时我们可以补充字符串结尾的\0保证(strncpy不会自动添加):
void String::copyString(const char *arr){ if(arr == nullptr){ initialize(); return; } size_t tempLen = strnlen(arr, MAX_LEN); len = tempLen; // strnlen返回的长度不会超过MAX_LEN,无需额外判断 initialize(); // 先释放原有内存(如果存在) charArr = new char[len + 1](); strncpy(charArr, arr, len); charArr[len] = '\0'; // 确保字符串以终止符结尾 }
验证修改后的代码
现在运行你的main()函数,就不会再出现内存错误了。所有构造函数都保证了charArr初始为nullptr,避免了野指针的问题,资源的分配和释放逻辑也更清晰严谨。
内容的提问来源于stack exchange,提问作者loay mansour

