为何触发Access Violation异常?C-string类成员函数报错求助
问题排查与修复方案
嘿,我一眼就瞅出你这0xC0000005访问违例的问题根源了——构造函数里调用length()成员函数时,memberString还没完成初始化!此时它要么是空指针(就是报错里的0x00000000访问位置),要么是随机野指针,直接调用strlen(memberString)去读它指向的内存,不触发异常才怪呢。
来拆解下你的代码逻辑问题:
MyString::MyString(const char* aString) { // 这里先调用了length(),但memberString还没被赋值! memberString = new char[length() + 1]; strcpy(memberString, aString); } int MyString::length() { return strlen(memberString); // 此时memberString是无效指针,访问非法内存 }
当构造函数刚执行时,memberString作为类的成员变量,默认初始化后要么是空指针(全局/静态对象),要么是随机垃圾值(局部对象),这时候你直接用它来调用strlen,肯定会触发内存访问错误。
两种可行的修复方案
我们的核心思路是:先拿到传入的aString的长度,而不是去读未初始化的memberString。
方案1:直接在构造函数里计算传入字符串的长度(推荐,最清晰)
MyString::MyString(const char* aString) { // 先处理aString是空指针的情况,默认按空字符串处理 size_t strLen = (aString == nullptr) ? 0 : strlen(aString); // 分配足够的内存(+1是给字符串结束符'\0'留位置) memberString = new char[strLen + 1]; // 同样处理空指针,避免strcpy访问无效地址 strcpy(memberString, aString ? aString : ""); } int MyString::length() { // 此时memberString已经被正确初始化,安全调用strlen return strlen(memberString); }
方案2:给length加临时判断(不推荐,复杂度更高)
如果你不想改构造函数的逻辑,也可以临时给length()加个判断,但这种方式会让函数逻辑变复杂,而且构造函数里用length()拿到的是0,分配的内存只能存空字符串,会截断传入的aString,所以还是方案1靠谱:
int MyString::length() { // 只有当memberString不是空指针时才调用strlen return memberString ? strlen(memberString) : 0; }
额外的健壮性建议
- 记得加析构函数释放内存,不然会造成内存泄漏:
MyString::~MyString() { delete[] memberString; } - 实现拷贝构造和拷贝赋值运算符(遵循C++的三/五法则),避免浅拷贝导致的重复释放内存问题。比如:
MyString::MyString(const MyString& other) { size_t strLen = strlen(other.memberString); memberString = new char[strLen + 1]; strcpy(memberString, other.memberString); } MyString& MyString::operator=(const MyString& other) { if (this != &other) { // 先释放当前内存 delete[] memberString; // 再拷贝新的内容 size_t strLen = strlen(other.memberString); memberString = new char[strLen + 1]; strcpy(memberString, other.memberString); } return *this; }
内容的提问来源于stack exchange,提问作者ashton
相关产品推荐
相关产品推荐

