C++矩阵程序触发Access violation错误,请求代码排查与规范指导
Hey there! Let's break down what's going wrong with your matrix code and fix those issues step by step.
Core Crash Cause Analysis
The immediate crash happens because of two critical mistakes in your copy constructor and assignment operator:
- Wrong operator usage: You used
==(comparison) instead of=(assignment) to setrowandcolvalues. Lines likerow == srcMatrix.row;do nothing but compare values—they don't actually assign the source matrix's dimensions to the new object. This leavesrowandcolas uninitialized garbage values, breaking all subsequent memory operations. - Invalid delete in copy constructor: The copy constructor initializes a brand-new object, so its
elementspointer is an uninitialized wild pointer. Checkingif (elements!= NULL) delete[]elements;and deleting this wild pointer directly triggers the access violation error you're seeing. - Incorrect memory deallocation: Your matrix uses a 2D dynamic array. You must first delete each row's array before deleting the top-level pointer array. Skipping this step causes memory leaks and potential crashes.
Other Non-Standard Code Issues
As a C++ beginner, there are several best practices you're missing:
using namespace std;in headers: This pollutes the global namespace and can cause naming conflicts in larger projects. Never do this—use fully qualified names likestd::coutin headers, or limitusing namespace std;to.cppfiles.- Wrong initialization order: Member variables are initialized in the order they're declared in the class, not the order you write in the initializer list. Your default constructor initializes
elementsfirst, butrowandcolare declared before it—this can lead to unexpected behavior. - Using
NULLinstead ofnullptr:nullptris the type-safe C++11 alternative to theNULLmacro, avoiding confusion with integer values. - No bounds checking: Your
setNumfunction doesn't verify if the input row/col indices are within valid ranges, making it easy to trigger array out-of-bounds errors. - No self-assignment protection: If you ever write
c = c, your current assignment operator would delete the object's memory first, then try to read from the already freed space—causing a crash. - Direct private member access: The
transposefunction directly modifiestemp.elements, which breaks encapsulation. It's better to use the publicsetNuminterface instead. - Missing destructor: You never free the dynamically allocated memory for your matrix, leading to permanent memory leaks.
Fixed Complete Code
Matrix.h (Header File)
#ifndef MATRIX_H #define MATRIX_H #include <iostream> class Matrix { int row; int col; double** elements; public: Matrix(); Matrix(int row, int col); Matrix(const Matrix& srcMatrix); Matrix& operator=(const Matrix& srcMatrix); ~Matrix(); // Critical: Destructor to free memory void setNum(double num, int rowIdx, int colIdx); Matrix transpose(); void display(); // Helper functions to get dimensions safely int getRow() const { return row; } int getCol() const { return col; } }; #endif // MATRIX_H
Matrix.cpp (Implementation File)
#include "Matrix.h" #include <iostream> #include <algorithm> // For std::swap using namespace std; Matrix::Matrix() : row(0), col(0), elements(nullptr) {} Matrix::Matrix(int row, int col) : row(row), col(col) { elements = new double*[row]; for (int i = 0; i < row; ++i) { elements[i] = new double[col](); // Initialize all elements to 0 } } // Copy Constructor Matrix::Matrix(const Matrix& srcMatrix) : row(srcMatrix.row), col(srcMatrix.col), elements(nullptr) { elements = new double*[row]; for (int i = 0; i < row; ++i) { elements[i] = new double[col](); } // Copy elements from source for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { elements[i][j] = srcMatrix.elements[i][j]; } } } // Assignment Operator (Copy-Swap Idiom - Safe & Clean) Matrix& Matrix::operator=(Matrix srcMatrix) { swap(row, srcMatrix.row); swap(col, srcMatrix.col); swap(elements, srcMatrix.elements); return *this; } // Destructor: Free all dynamically allocated memory Matrix::~Matrix() { if (elements!= nullptr) { // Free each row first for (int i = 0; i < row; ++i) { delete[] elements[i]; } // Free the top-level pointer array delete[] elements; elements = nullptr; } } void Matrix::setNum(double num, int rowIdx, int colIdx) { // Bounds checking to prevent out-of-bounds access if (rowIdx >= 0 && rowIdx < row && colIdx >= 0 && colIdx < col) { elements[rowIdx][colIdx] = num; } else { cerr << "Error: Index out of bounds!" << endl; } } Matrix Matrix::transpose() { Matrix temp(col, row); for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { temp.setNum(elements[i][j], j, i); // Use public interface instead of direct access } } return temp; } void Matrix::display() { for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { cout << elements[i][j] << " "; } cout << endl; } }
main.cpp
#include <iostream> #include "Matrix.h" using namespace std; int main() { double a[3] = {1.0, 3.0, 2.0}; double b[3] = {2.0, 3.0, 4.0}; Matrix c(2, 3); for (int i = 0; i < 3; ++i) { c.setNum(a[i], 0, i); c.setNum(b[i], 1, i); } c = c.transpose(); c.display(); return 0; }
Key Fixes Explained
- Added Destructor: Properly frees the 2D array memory to avoid leaks and crashes.
- Fixed Copy Constructor: Removed invalid delete, correctly initializes dimensions, and safely copies elements.
- Copy-Swap Idiom for Assignment: Automatically handles self-assignment and simplifies code—this is a standard C++ best practice.
- Bounds Checking:
setNumnow validates input indices to prevent memory access errors. - Header Guards: Prevents duplicate inclusion of the header file.
- Proper Initialization Order: Aligns the initializer list with the class member declaration order.
内容的提问来源于stack exchange,提问作者BlackieMia
相关产品推荐
相关产品推荐

