Visual Studio运行C++自定义字符串类代码触发0xC0000005访问违规异常的原因排查
Hey there! Let's break down why you're hitting that access violation error in your mystring class, and fix it step by step.
The Root Causes of the Access Violation
Your error happens because of a few critical issues with how your mystring class manages memory and uses strcat:
- No independent memory management: Your constructor just assigns the input
char*directly topinstead of allocating new memory and copying the string. This means multiplemystringobjects can point to the same underlying character array. For example, when you domystring t1(i);andmystring s2(i);, botht1.pands2.ppoint to the samei[100]array on the stack. When you callt1 + s2,strcat(p, z.p)tries to concatenate the array onto itself—strcathas undefined behavior when the source and destination buffers overlap, which leads to memory corruption and access violations. - Insufficient buffer space: Even without overlap, if you keep concatenating strings onto a fixed-size stack array (like
i[100]), you'll eventually exceed its capacity, causing stack overflow and access violations. - Missing essential class functions: You don't have a destructor to free memory (once you start allocating it), a copy constructor, or an assignment operator—this leads to shallow copies and memory leaks or double-free errors later.
Fixed Code with Proper Memory Management
Here's a revised version of your class that fixes these issues, following C++ best practices for string handling:
#include <iostream> #include <cstring> #pragma warning(disable:4996) using namespace std; class mystring { private: char* p; int length; // Stores the length of the string (including null terminator) public: // Constructor: Allocate memory and copy input string mystring(const char* ps) { length = strlen(ps) + 1; p = new char[length]; strcpy(p, ps); } // Destructor: Free allocated memory to prevent leaks ~mystring() { delete[] p; } // Copy constructor: Deep copy to avoid sharing memory mystring(const mystring& other) { length = other.length; p = new char[length]; strcpy(p, other.p); } // Assignment operator: Deep copy and handle self-assignment mystring& operator=(const mystring& other) { if (this != &other) { delete[] p; // Free existing memory length = other.length; p = new char[length]; strcpy(p, other.p); } return *this; } // Overload operator+ for char*: Return a new mystring with concatenated result mystring operator+(const char* s) const { int newLength = length + strlen(s); char* temp = new char[newLength]; strcpy(temp, p); strcat(temp, s); mystring result(temp); delete[] temp; // Clean up temporary buffer return result; } // Overload operator+ for mystring: Return a new mystring with concatenated result mystring operator+(const mystring& z) const { int newLength = length + z.length - 1; // Subtract 1 to avoid double-counting null terminator char* temp = new char[newLength]; strcpy(temp, p); strcat(temp, z.p); mystring result(temp); delete[] temp; return result; } // Friend operator+ for char* + mystring friend mystring operator+(const char* d, const mystring& s) { int newLength = strlen(d) + s.length; char* temp = new char[newLength]; strcpy(temp, d); strcat(temp, s.p); mystring result(temp); delete[] temp; return result; } void print() const { cout << p; } }; int main() { char t[300] = "def", i[100] = "abc"; mystring t1(i); t1 = t1 + t; t1.print(); cout << endl; // Add newline for readability mystring s2(i); t1 = t1 + s2; t1.print(); cout << endl; mystring s3(i); t1 = i + s3; t1.print(); cout << endl; return 0; }
Key Changes Explained
- Independent memory allocation: The constructor now allocates a new char array for each
mystringobject, so no two objects share the same memory. This eliminates overlap issues withstrcat. - Destructor, copy constructor, assignment operator: These ensure proper memory management—no leaks, no double-frees, and no shallow copies.
- Operator+ returns new objects: Instead of modifying the original
mystring(which is counterintuitive for string concatenation, just likestd::string), we create a newmystringwith the concatenated result. This avoids modifying the original object and prevents unexpected side effects. - Const correctness: We added
constto parameters and member functions that don't modify the object, which is good practice in C++.
Why This Fixes the Access Violation
By allocating separate memory for each string, we never have overlapping source/destination buffers for strcat. We also calculate the exact size needed for concatenated strings, so we never write beyond the bounds of the allocated memory. All memory is properly managed, so there's no risk of stack overflow or invalid memory access.
内容的提问来源于stack exchange,提问作者Kaiyu Yang

