You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. Wrong operator usage: You used == (comparison) instead of = (assignment) to set row and col values. Lines like row == srcMatrix.row; do nothing but compare values—they don't actually assign the source matrix's dimensions to the new object. This leaves row and col as uninitialized garbage values, breaking all subsequent memory operations.
  2. Invalid delete in copy constructor: The copy constructor initializes a brand-new object, so its elements pointer is an uninitialized wild pointer. Checking if (elements!= NULL) delete[]elements; and deleting this wild pointer directly triggers the access violation error you're seeing.
  3. 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 like std::cout in headers, or limit using namespace std; to .cpp files.
  • 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 elements first, but row and col are declared before it—this can lead to unexpected behavior.
  • Using NULL instead of nullptr: nullptr is the type-safe C++11 alternative to the NULL macro, avoiding confusion with integer values.
  • No bounds checking: Your setNum function 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 transpose function directly modifies temp.elements, which breaks encapsulation. It's better to use the public setNum interface 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: setNum now 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 23:07:35