删除动态分配的二维数组时发生错误?

Posted

技术标签:

【中文标题】删除动态分配的二维数组时发生错误?【英文标题】:Error happens during deleting the dynamic allocated 2d array? 【发布时间】:2018-02-08 04:25:41 【问题描述】:

我正在学习 c++,并制作了带有操作的矩阵生成类的代码。

但是,当我尝试在整个工作后删除用户输入的两个矩阵时,它会弹出消息:

“在 Matrix 1.3.exe 中的 0x0F4DBF9B (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突读取位置 0xDDDDDDCD”

在“(45)delete[] arr[i];”行,在析构函数中。

我试图删除括号,但由于我需要这些括号来删除数组,它也不起作用。

你知道这里出了什么问题吗?

#include <iostream>
#include <iomanip>

using namespace std;

class Matrix

private:
    int row, col;
    int** arr;
public:
    Matrix(int, int);
    ~Matrix();

    int getRow() const;
    int getCol() const;
    int** getMatrixArr() const;

    friend Matrix* operator+(const Matrix&, const Matrix&);
    friend Matrix* operator-(const Matrix&, const Matrix&);
    friend Matrix* operator*(const Matrix&, const Matrix&);
    friend Matrix* operator*(const Matrix&, int);
    friend ostream& operator<<(ostream&, const Matrix*);
    friend istream& operator>>(istream&, const Matrix&);

;

//construct and destruct--------------------------------------------------------------------------------------------------

Matrix::Matrix(int row, int col)

    this->row = row;
    this->col = col;
    arr = new int*[row];
    for (int i = 0; i < row; i++)
    
        arr[i] = new int[col];
    


Matrix::~Matrix()

    for (int i = 0; i < row; i++)
    
        delete[] arr[i];
    
    delete[] arr;


//getters------------------------------------------------------------------------------------------------------------------
int Matrix::getRow() const

    return row;


int Matrix::getCol() const

    return col;

int** Matrix::getMatrixArr() const

    return arr;



//operation methods(OpOv)----------------------------------------------------------------------------------------------------------

Matrix* operator+(const Matrix& m, const Matrix& n)

    Matrix* sum = new Matrix(m.row, m.col);
    cout << "calculating..." << endl;

    for (int i = 0; i <m.row; i++)
    
        for (int j = 0; j <m.col; j++)
        
            cout << setw(3) << m.arr[i][j] << "+" << n.arr[i][j];
            sum->arr[i][j] = m.arr[i][j] + n.arr[i][j];
        
        cout << endl;
    
    return sum;


Matrix* operator-(const Matrix& m, const Matrix& n)

    Matrix* sum = new Matrix(m.row, m.col);
    cout << "caluclating..." << endl;

    for (int i = 0; i < m.row; i++)
    
        for (int j = 0; j < m.col; j++)
        
            cout << setw(3) << m.arr[i][j] << "-" << n.arr[i][j];
            sum->arr[i][j] = m.arr[i][j] - n.arr[i][j];
        
        cout << endl;
    
    return sum;


Matrix* operator*(const Matrix& m, const Matrix& n)

    Matrix* sum = new Matrix(m.row, n.col);
    cout << "calculating..." << endl;

    for (int i = 0; i < m.row; i++)
    
        for (int j = 0; j < n.col; j++)
        
            sum->arr[i][j] = 0;
        
    

    for (int i = 0; i < m.row; i++)
    
        for (int j = 0; j < n.col; j++)
        
            for (int t = 0; t < m.col; t++)
            
                cout << setw(3) << "+" << m.arr[i][t] << "x" << n.arr[t][j];
                sum->arr[i][j] += m.arr[i][t] * n.arr[t][j];
            
        
        cout << endl;
    

    return sum;


Matrix* operator*(const Matrix& m, int num)

    Matrix* sum = new Matrix(m.row, m.col);
    cout << "calculating..." << endl;
    for (int i = 0; i < m.row; i++)
    
        for (int j = 0; j < m.col; j++)
        
            cout << setw(3) << m.arr[i][j] << "x" << num;
            sum->arr[i][j] = m.arr[i][j] * num;
        
        cout << endl;
    

    return sum;


// input & output ---------------------------------------------------------------------------------------------------------------------

istream& operator>>(istream& is, const Matrix& m)

    cout << "Enter the values for the Matrix (expecting: " << m.row * m.col << "): ";
    for (int i = 0; i < m.row; i++)
    
        for (int j = 0; j < m.col; j++)
        
            is >> m.arr[i][j];
        
    
    return is;



ostream& operator<<(ostream& os, const Matrix* m)

    cout << "result: " << endl;
    for (int i = 0; i < m->row; i++)
    
        for (int j = 0; j < m->col; j++)
        
            os << setw(3) << m->arr[i][j];
        
        cout << endl;
    
    return os;


//main-------------------------------------------------------------------------------------------------------------------------------------
int main()


    int rowNum1, colNum1;

    cout << "what is the row of the Matrix 1?: " << endl;
    cin >> rowNum1;
    cout << "What is the column for the Matrix 1?: " << endl;
    cin >> colNum1;
    Matrix m1(rowNum1, colNum1);

    cin >> m1;


    int rowNum2, colNum2;

    cout << "what is the row of the Matrix 2?: " << endl;
    cin >> rowNum2;
    cout << "What is the column for the Matrix 2?: " << endl;
    cin >> colNum2;
    Matrix m2(rowNum2, colNum2);

    cin >> m2;

    int choice;
    do
    
        cout << "Now, what operation do you want to use?" << endl;
        cout << "1) addition, 2) Sub action, 3)Multiplication, 4) scalar multiplication 5) quit" << endl << ":";
        cin >> choice;

        if (choice == 1)
        
            if (m1.getRow() != m2.getRow() || m1.getCol() != m2.getCol())
            
                cout << "The number of rows or columns of both Matrices are not same, you cannot add them together." << endl;
                return 0;
            
            else
            

                Matrix * result = (m1 + m2);
                cout << result << endl;
            
        

        else if (choice == 2)
        
            if (m1.getRow() != m2.getRow() || m1.getCol() != m2.getCol())
            
                cout << "The number of rows or columns of both Matrices are not same, you cannot add them together." << endl;
                return 0;
            
            else
            
                Matrix * result = (m1 - m2);
                cout << result << endl;
            
        

        else if (choice == 3)
        
            if (m1.getCol() != m2.getRow())
            
                cout << "Your first Matrix's number of columns and the second Matrice's number of rows are not accorded." << endl;
                return 0;
            
            else
            
                Matrix* result =  (m1 * m2);
                cout << result << endl;
            
        

        else if (choice == 4)
        
            int value;
            cout << "What is the integer value for the multiplication?: ";
            cin >> value;

            int MatCho;
            cout << "First Matrix or Second Matrix(1 or 2)?: ";
            cin >> MatCho;

            if (MatCho == 1)
            
                Matrix* result = (m1 * value);
                cout << result << endl;
            
            else if (MatCho == 2)
            
                Matrix* result = (m2 * value);
                cout << result << endl;
            
            else
            
                cout << "invalid input" << endl;
            
        
        else if (choice == 5)
        
            break;
        
        else
        
            cout << "Invalid input" << endl;
        
     while (choice != 5);

    m1.~Matrix();
    m2.~Matrix();


    return 0;

【问题讨论】:

你为什么不直接调用delete m1; delete m2,你还需要在析构函数中使用delete[] arr;,因为你已经在循环逐行销毁了。 @macroland:你不能删除 m1; m1 是堆栈上的对象,而不是指向动态内存的指针。还有 delete[] arr;是必需的,指向每个矩阵行的指针数组也需要删除。 @Morgan:是的,刚刚意识到他们在堆栈上。 【参考方案1】:

这里有两个问题:

    永远不要像在此处使用 m1 和 m2 那样显式调用析构函数。在任何情况下,它们的析构函数都会在主函数结束时自动调用。所以对你来说,析构函数将运行两次。在第二次运行时,指针数组已被删除。但是 row、col 和指针仍然有它们的旧值,并且会尝试访问和删除已经释放的内存。

    您对矩阵执行的所有操作都会泄漏内存。您在运算符函数中使用 new 但从不删除结果。期望函数的用户删除您分配的内存是一个坏习惯。而是按值返回。如果您实现移动构造函数,这实际上不会推断出任何性能损失 (http://www.learncpp.com/cpp-tutorial/15-3-move-constructors-and-move-assignment/)

【讨论】:

【参考方案2】:

删除对析构函数的手动调用。由于它们是堆栈分配的,因此您使用的 C++ 编译器将在您退出主函数时处理它们,即使您已经调用了它们(正在发生的事情)。

【讨论】:

以上是关于删除动态分配的二维数组时发生错误?的主要内容,如果未能解决你的问题,请参考以下文章

如果 C++ 程序发生错误,如何删除动态分配的对象?

二维数组动态内存分配崩溃[重复]

c++ 动态分配二维数组 new 二维数组

动态分配的二维数组

将二维数组复制到函数外部动态分配的二维数组

在 C++ 中的 2D 动态内存分配数组中释放分配的内存