简体   繁体   中英

Error happens during deleting the dynamic allocated 2d array?

I am learning c++ and made my code of Matrix generating Class with operations.

However, When I try to delete the two matrices which input by user after the whole works, it pops up the message:

"Exception thrown at 0x0F4DBF9B (ucrtbased.dll) in Matrix 1.3.exe: 0xC0000005: Access violation reading location 0xDDDDDDCD"

at "(45)the delete[] arr[i];" line, which is in the destructor.

I tried to remove the brackets, but as I need those brackets to remove arrays, it also did not work.

Do you have any idea whats going wrong here?

#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;
}

Two issues here:

  1. Never call destructor explicitly like you do with m1 and m2 here. Their destructors will be called automatically at the end of the main function in any case. So for you the destructors will run twice. On the second run, the array of pointers has already been deleted. But row, col and the pointer still has their old values and will try to access and delete already freed memory.

  2. All your operations you do on the matrices will leak memory. You are using new inside the operator functions but never deleting the result. It is a bad habit expecting the user of a function to delete memory you have allocated. Return by value instead. This will actually not infer any performance loss, if you implement a move constructor ( http://www.learncpp.com/cpp-tutorial/15-3-move-constructors-and-move-assignment/ )

Remove the manual call to the destructors. As they're stack-allocated, the C++ compiler you use will handle them when you exit the main function, even if you already called them (which is what is happening).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM