VS2017 Community中C++程序崩溃问题求助
Hey there! Let's break down this weird, inconsistent crash issue you're hitting with your C++ class. Random crash locations (constructor, show() method, or even after main() returns) are a classic sign of heap memory corruption—usually from double-freeing memory or accessing invalid memory addresses.
Looking at your main() code line:
MyScreen scr = MyScreen(10, 10);
This uses copy initialization, which triggers the copy constructor. If you didn't write a custom copy constructor for MyScreen, the compiler generates a default one that does a shallow copy.
Here's the problem: if your MyScreen class has pointer members (like a dynamically allocated buffer for screen data), the default copy constructor only copies the pointer value—not the data it points to. That means both the temporary MyScreen(10,10) object and your scr variable end up sharing the same block of heap memory.
When the program exits:
- The temporary object gets destroyed first, freeing the shared memory.
- Then
scrgets destroyed, trying to free the same memory again—this is a double-free, which corrupts the heap. The crash might not happen immediately, which is why it pops up in random places.
1. Implement the "Rule of Three" (For C03/C11)
If your class manages dynamic memory, you need to explicitly define three functions to avoid shallow copy issues:
- Copy constructor (deep copies the data)
- Copy assignment operator
- Destructor (properly cleans up memory)
Example implementation for MyScreen:
#include <cstring> #include <iostream> class MyScreen { private: int width; int height; char* screenBuffer; // Dynamic buffer example public: // Constructor MyScreen(int w, int h) : width(w), height(h) { screenBuffer = new char[w * h]; std::memset(screenBuffer, ' ', w * h); // Initialize to spaces } // Copy Constructor (Deep Copy) MyScreen(const MyScreen& other) : width(other.width), height(other.height) { screenBuffer = new char[width * height]; std::memcpy(screenBuffer, other.screenBuffer, width * height); } // Copy Assignment Operator MyScreen& operator=(const MyScreen& other) { if (this == &other) return *this; // Handle self-assignment // Free existing memory first delete[] screenBuffer; // Deep copy new data width = other.width; height = other.height; screenBuffer = new char[width * height]; std::memcpy(screenBuffer, other.screenBuffer, width * height); return *this; } // Destructor ~MyScreen() { delete[] screenBuffer; } void show() { for (int i = 0; i < height; ++i) { std::cout << std::string(screenBuffer + i * width, width) << "\n"; } } };
2. Quick Fix: Use Direct Initialization
If you want to avoid the copy temporarily (while you implement the Rule of Three), switch to direct initialization in main()—this skips creating the temporary object and the copy operation:
int main() { MyScreen scr(10, 10); // Direct initialization, no copy scr.show(); char ch; std::cin >> ch; return 0; }
3. Debugging Tip: Track Object Lifecycle
Add print statements to your constructors and destructor to see how many objects are created/destroyed:
MyScreen(int w, int h) { std::cout << "Constructor called for object at: " << this << "\n"; // ... rest of constructor logic } MyScreen(const MyScreen& other) { std::cout << "Copy constructor called for object at: " << this << " (copied from: " << &other << ")\n"; // ... rest of copy constructor logic } ~MyScreen() { std::cout << "Destructor called for object at: " << this << "\n"; // ... rest of destructor logic }
This will show you exactly when objects are being copied and destroyed, making it easy to spot duplicate destructor calls on the same memory.
内容的提问来源于stack exchange,提问作者Jeidoz

