C++ Access violation reading location 0xCCCCCCBC

0

I'm writing a program that implements some functions of matrix but get into trouble at the beginning stage.

When debugging goes to c = c.transpose(); in the main function,it steps into the copy constructor and throws an exception at the statement:delete[]elements;. And it says:

Unhandled exception at 0x7CBDDB1B (ucrtbased.dll) in Exercise2.2.exe: 0xC0000005: Access violation reading location 0xCCCCCCBC.

enter image description here

I have no idea what happens. I would appreciate it if someone could take a look at my code.

Btw, I'm a C++ beginner, so besides the error, if there are codes that are not of standard, please point it out.

header:

#include <iostream>
using namespace std;
class Matrix
{
    int row;
    int col;
    double **elements;
public:
    Matrix();
    Matrix(int row, int col);
    Matrix(const Matrix& srcMatrix);
    Matrix& operator=(const Matrix& srcMatrix);
    void setNum(double Num, int row,int col);
    Matrix transpose();
    void display();
};

Matrix::Matrix():elements(0),row(0),col(0){}

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

Matrix::Matrix(const Matrix& srcMatrix){
    row == srcMatrix.row;
    col == srcMatrix.col;
    if (elements != NULL) {
        delete[]elements;
    }
    elements = new double* [row];
    for (int i = 0;i < row;i++) {
        elements[i] = new double[col];
    }
    for (int i = 0;i < row;i++) {
        for(int j = 0;j < col;j++) {
            elements[i][j] = srcMatrix.elements[i][j];
        }
    }
}

Matrix& Matrix::operator=(const Matrix& srcMatrix) {
    row == srcMatrix.row;
    col == srcMatrix.col;
    if (elements != NULL) {
        delete[]elements;
    }
    elements = new double* [row];
    for (int i = 0;i < row;i++) {
        elements[i] = new double[col];
    }
    for (int i = 0;i < row;i++) {
        for (int j = 0;j < col;j++) {
            elements[i][j] = srcMatrix.elements[i][j];
        }
    }
    return *this;
}

void Matrix::setNum(double Num, int row, int col) {
    elements[row][col] = Num;
}

Matrix Matrix::transpose() {
    Matrix temp(col,row);
    for (int i = 0;i < row;i++) {
        for (int j = 0;j < col;j++) {
            temp.elements[j][i] = elements[i][j];
        }
    }
    return temp;
}

void Matrix::display() {
    for (int i = 0;i < row;i++) {
        for (int j = 0;j < col;j++) {
            cout << elements[i][j] << " ";
            if (j == col - 1) {
                cout << endl;
            }
        }
    }
}

Main function:

#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;
} 
c++
asked on Stack Overflow Mar 19, 2020 by BlackieMia • edited Mar 19, 2020 by James Z

2 Answers

3
Matrix::Matrix(const Matrix& srcMatrix){
    ...
    if (elements != NULL) {
        delete[]elements;
    }

You never initialised elements in this constructor. You leave it with indeterminate value, but read its value when comparing to null, and then attempt to delete it, both of which result in undefined behaviour.

You are constructing a new object. It cannot possibly own any elements before you create them, so there is nothing to delete either.

row == srcMatrix.row;
col == srcMatrix.col;

These comparisons, and later use as array size also read members whose values are indeterminate due to lack of initialisation. I suspect that you instead intended to assign the members. Assignment operator is single = not two. That said, it's better to initialise the members instead of assigning later.


Also, unless you need to support ancient compilers, use nullptr instead of NULL. Also, if you use NULL, you should include the header which defines it.

answered on Stack Overflow Mar 19, 2020 by eerorika • edited Mar 20, 2020 by eerorika
0

Your copy and constructor and operator=are deleting an unitialised variable. There is no need to delete elements in any case as it has never been allocated in the first instance - you do that later.

Remove the part:

if (elements != NULL) {
    delete[]elements;
}

from both. Or better since your copy constructor and operator= contain identical code, create a copy function and use that from both. The operator= should also have a self assignment check so that expressions such as x = x are safe:

Matrix::Matrix(const Matrix& srcMatrix)
{
    this->copy( srcMatrix ) ;
}

Matrix& Matrix::operator=(const Matrix& srcMatrix) 
{
    if( this != &srcMatrix ) this->copy( srcMatrix ) ;

    return *this
}
answered on Stack Overflow Mar 19, 2020 by Clifford • edited Mar 19, 2020 by Clifford

User contributions licensed under CC BY-SA 3.0