Ошибка при вызове деструктора. Язык C++

Всем привет, столкнулся с проблемой что, возникает ошибка(Exception thrown at 0x00007FFA51B8030E (ucrtbased.dll) in HomeworkFor1-2Module.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.) при вызове деструктора, причем она появляется в самом конце когда были выполнены все алгоритмы. Деструктор выглядит так:

~MatrixClass()
{
    for (int i = 0; i < lines; i++)
    {
        delete[] matrix[i];
    }
    delete[] matrix;
    cout << "Matrix deleted" << endl;
}

В нем удаляется двумерный массив, представляющий из себя матрицу размером lines x columns. Моя цель была реализовать класс матрицы "MatrixClass" для различных манипуляций с матрицами. Вот так выглядит файл MatrixClass.h:

#include <iostream>
#include <fstream>
#include "Types.h"
#include <vector>
#include <string> 
using namespace std;

template <typename T>
class MatrixClass
{
public:
    ~MatrixClass()
    {
        for (int i = 0; i < lines; i++)
        {
            delete[] matrix[i];
        }
        delete[] matrix;
        cout << "Matrix deleted" << endl;
    }

    static MatrixClass ZeroMatrix(int lines, int columns)
    {
        MatrixClass<float> ZeroMat(columns, lines);
        ZeroMat.ZeroInitializeMatrix();
        return ZeroMat;
    }

    static MatrixClass ASingleMatrix(int lines, int columns)
    {
        MatrixClass<float> SingleMat(columns, lines);
        SingleMat.ZeroInitializeMatrix();
        for (int i = 0; i < columns; i++)
            for (int j = 0; j < lines; j++)
                if (i == j)
                {
                    SingleMat.matrix[i][j] = 1;
                    break;
                }

        return SingleMat;
    }

    MatrixClass(PlaceForMatrix Place)
    {
        switch (Place)
        {
        case PlaceForMatrix::None:
            break;
        case PlaceForMatrix::Console:
        {
            Place = PlaceForMatrix::Console;

            cout << "Write count of lines:" << endl;
            cin >> lines;

            cout << "Write count of columns:" << endl;
            cin >> columns;
            ReadMatrixFromConsole();
            break;
        }
        case PlaceForMatrix::File:
        {
            Place = PlaceForMatrix::File;
            break;
        }

        default:
            break;
        }
    }

    MatrixClass(MatrixClass& mat)
    {
        lines = mat.lines;
        columns = mat.columns;
        matrix = new float* [mat.lines];
        for (int i = 0; i < (mat.lines >= mat.columns ? mat.lines : mat.columns); i++)
            matrix[i] = new float[mat.columns];
    }

    MatrixClass(int columns, int lines)
    {
        this->lines = lines;
        this->columns = columns;
        matrix = new float* [lines];
        for (int i = 0; i < lines; i++)
            matrix[i] = new float[columns];
    }

    void ReadMatrixFromFile(char* FilePath)
    {
        CalculateParametrsOfMatrix(FilePath);
        CreateMatrix();
        ZeroInitializeMatrix();
        InitializeMatrixFromFile(FilePath);
    }

    void ReadMatrixFromConsole()
    {
        cout << "Write elements of matrix(you can use only space):" << endl;
        CreateMatrix();
        ZeroInitializeMatrix();
        InitializeMatrixFromConsole();
        cout << endl;
    }

    void ReadMatrixFromVariable(int** variable)
    {
        CreateMatrix();
        ZeroInitializeMatrix();
    }

    void ShowMatrix()
    {
        for (int i = 0; i < lines; i++)
            for (int j = 0; j < columns; j++)
            {
                if (j == columns - 1)
                {
                    cout << matrix[j][i] << endl;
                }
                else
                {
                    cout << matrix[j][i] << " ";
                }
            }
        cout << endl;
    }

    void ShowMatrix(float** matrix, int rows, int cols)
    {
        for (int i = 0; i < rows; i++)
            for (int j = 0; j < cols; j++)
            {
                if (j == cols - 1)
                {
                    cout << matrix[j][i] << endl;
                }
                else
                {
                    cout << matrix[j][i] << " ";
                }
            }
        cout << endl;
    }

    void ConsolePrint() {
        cout << endl;
        for (int i = 0; i < lines; i++) {
            for (int j = 0; j < columns; j++)
                cout << matrix[i][j] << " ";
            cout << endl;
        }
    }

    void ChangePlaceOfLines(int FirstLine, int SecondLine)
    {
        FirstLine -= 1;
        SecondLine -= 1;
        for (int i = 0; i < columns; i++)
        {
            int s = matrix[i][FirstLine];
            matrix[i][FirstLine] = matrix[i][SecondLine];
            matrix[i][SecondLine] = s;
        }
    }

    void MultiplyLine(int Line, int Multiplier)
    {
        Line -= 1;
        for (int i = 0; i < columns; i++)
        {
            matrix[i][Line] *= Multiplier;
        }
    }

    void LinePlusMultiplyLine(int FirstLine, int SecondLine, int Multiplier)
    {
        FirstLine -= 1;
        SecondLine -= 1;
        for (int i = 0; i < columns; i++)
        {
            matrix[i][FirstLine] += matrix[i][SecondLine] * Multiplier;
        }
    }

    void operator*(MatrixClass& Matrix)
    {
        if (columns != Matrix.lines)
        {
            cout << "Can't do this!(columns != Matrix.lines)" << endl;
        }

        int CountOfElements = lines * Matrix.columns;
        int HalfCountOfElements;
        int ln = lines;
        int col = Matrix.columns;
        if (CountOfElements % 2 == 0)
        {
            HalfCountOfElements = CountOfElements / 2;
        }
        else
        {
            HalfCountOfElements = CountOfElements / 2 - 1;
        }
        float** NewMat = new float* [ln];//массив указателей
        for (int i = 0; i < ln; i++)
        {
            NewMat[i] = new float[col];
        }

        int element;
        int SdvigLine = 0;
        int SdvigCol = 0;

        while (SdvigLine != ln)
        {
            while (SdvigCol != col)
            {
                element = 0;
                for (int i = 0; i < columns; i++)
                {
                    element += matrix[i][SdvigLine] * Matrix.matrix[SdvigCol][i];
                }
                NewMat[SdvigLine][SdvigCol] = element;
                SdvigCol += 1;
            }
            SdvigLine += 1;
            SdvigCol = 0;
        }
        ShowMatrix(NewMat, ln, col);
    }

    void operator*(int scalar)
    {
        for (int i = 0; i < lines; i++)
            for (int j = 0; j < columns; j++)
                matrix[j][i] *= 2;

        ShowMatrix();
    }

    void operator+(MatrixClass& Matrix)
    {
        if (lines != Matrix.lines || columns != Matrix.columns)
        {
            cout << "You cant do this" << endl;
        }
        else
        {
            int CountOfElements = lines * Matrix.columns;
            int HalfCountOfElements;
            if (CountOfElements % 2 == 0)
            {
                HalfCountOfElements = CountOfElements / 2;
            }
            else
            {
                HalfCountOfElements = CountOfElements / 2 - 1;
            }
            float** NewMat = new float* [HalfCountOfElements];//массив указателей
            for (int i = 0; i < HalfCountOfElements; i++)
            {
                NewMat[i] = new float[HalfCountOfElements];
            }

            for (int i = 0; i < HalfCountOfElements; i++)
                for (int j = 0; j < HalfCountOfElements; j++)
                    NewMat[j][i] = matrix[j][i] + Matrix.matrix[j][i];

            ShowMatrix(NewMat, HalfCountOfElements, HalfCountOfElements);
        }
    }

    void operator-(MatrixClass& Matrix)
    {
        if (lines != Matrix.lines || columns != Matrix.columns)
        {
            cout << "You cant do this" << endl;
        }
        else
        {
            int CountOfElements = columns * Matrix.lines;
            int HalfCountOfElements;
            if (CountOfElements % 2 == 0)
                HalfCountOfElements = CountOfElements / 2;
            else
                HalfCountOfElements = CountOfElements / 2 - 1;
            float** NewMat = new float* [HalfCountOfElements];//массив указателей
            for (int i = 0; i < HalfCountOfElements; i++)
                NewMat[i] = new float[HalfCountOfElements];

            for (int i = 0; i < HalfCountOfElements; i++)
                for (int j = 0; j < HalfCountOfElements; j++)
                    NewMat[i][j] = matrix[i][j] - Matrix.matrix[i][j];

            ShowMatrix(NewMat, HalfCountOfElements, HalfCountOfElements);
        }
    }

    bool operator==(MatrixClass& Matrix)
    {
        if (lines != Matrix.lines || columns != Matrix.columns)
        {
            return false;
        }
        int CountOfElements = lines * Matrix.columns;
        int HalfCountOfElements;
        if (CountOfElements % 2 == 0)
        {
            HalfCountOfElements = CountOfElements / 2;
        }
        else
        {
            HalfCountOfElements = CountOfElements / 2 - 1;
        }

        int count = 0;
        for (int i = 0; i < HalfCountOfElements; i++)
            for (int j = 0; j < HalfCountOfElements; j++)
                if (matrix[j][i] == Matrix.matrix[j][i])
                    count += 1;

        if (count != CountOfElements)
            return false;
        else
            return true;
    }

    bool operator==(int scalar)
    {
        for (int i = 1; i < lines; i++)
            if (matrix[i][i] != scalar)
                return false;

        for (int i = 0; i < lines; i++)
            for (int j = 0; j < columns; j++)
                if (i != j && matrix[j][i] != 0)
                    return false;

        return true;
    }

    bool operator!=(MatrixClass& Matrix)
    {
        return !(matrix == Matrix.matrix);
    }

    void operator=(MatrixClass &Matrix)
    {
        matrix = Matrix.matrix;
        columns = Matrix.columns;
        lines = Matrix.lines;
    }

    void ZeroInitializeMatrix()
    {
        for (int i = 0; i < lines; i++)
            for (int j = 0; j < columns; j++)
                matrix[j][i] = 0;
    }

    void CalculateParametrsOfMatrix(char* FilePath)
    {
        ifstream in(FilePath);// окрываем файл для чтения
        if (in.is_open())
        {
            while (!in.eof())
            {
                char ch = NULL;
                while (ch != EOF)
                {
                    ch = in.get();
                    if (ch == ' ' || ch == '\n' || ch == EOF)
                    {
                        if (ch == '\n' || ch == EOF)
                            lines += 1;
                        else if (ch == ' ' && lines == 0)
                            columns += 1;
                    }
                }
            }
            columns += 1;
        }
        else
        {
            cout << "Is not open" << endl;
        }
        in.close();     // закрываем файл
    }

    void InitializeMatrixFromFile(char* FilePath)
    {
        ifstream in(FilePath);// окрываем файл для чтения
        int n;
        if (in.is_open())
        {
            int cols = 0;
            int rows = 0;
            while (in >> n)
            {
                matrix[cols][rows] = n;
                cols += 1;
                if (cols == columns)
                {
                    cols = 0;
                    rows += 1;
                }
            }
        }
        else
        {
            cout << "Error to open file" << endl;
        }
        in.close();
    }

    void InitializeMatrixFromConsole()
    {
        int n;
        int elements = 0;
        int cols = 0;
        int rows = 0;

        while (cin >> n)
        {
            elements += 1;
            matrix[cols][rows] = n;
            cols += 1;
            if (cols == columns)
            {
                cols = 0;
                rows += 1;
            }
            if (elements == (lines * columns))
                break;
        }
    }

    void CreateMatrix()
    {
        matrix = new float* [lines];//массив указателей
        for (int i = 0; i < (lines >= columns ? lines : columns); i++)
        {
            matrix[i] = new float[columns];
        }
    }

    int opredelitel() {
        if (columns != lines) {
            cout << "Cant get determinant" << endl;
            return 0;
        }
        if (lines == 1) {
            return matrix[0][0];
        }
        int opred = 0;
        if (lines == 2) {
            opred = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
        }
        else {
            for (int n = 0; n < lines; n++) {
                MatrixClass<vector<int>> algdop(lines - 1, columns - 1);
                for (int i = 1; i < lines; i++) {
                    int flag = 0;
                    for (int j = 0; j < columns; j++) {
                        if (j == n)
                            flag = 1;

                        if (j != n) {
                            algdop.matrix[i - 1][j - flag] = matrix[i][j];

                        }
                    }
                }
                opred = opred + pow(-1, 1 + (n + 1)) * matrix[0][n] * algdop.opredelitel();
            }
        }
        return opred;
    }

    MatrixClass operator!() {
        MatrixClass<float> obratn_matr(lines, columns);
        float opred = opredelitel();
        if (opred == 0) {
            cout << "Cant get reverse matrix" << endl;
            obratn_matr.ZeroInitializeMatrix();
            return obratn_matr;
        }
        else if (lines != columns) {
            cout << "Cant get reverse matrix" << endl;
            obratn_matr.ZeroInitializeMatrix();
            return obratn_matr;
        }

        else if (lines == 1 && columns == 1) {
            obratn_matr.matrix[0][0] = 1 / matrix[0][0];
            return obratn_matr;
        }
        MatrixClass<float> dop_matr(lines - 1, columns - 1);
        for (int i = 0; i < lines; i++) {
            for (int j = 0; j < columns; j++) {
                int flagi = 0;
                int flagj = 0;
                for (int n = 0; n < lines - 1; n++) {
                    if (n == i)
                        flagi = 1;
                    flagj = 0;
                    for (int m = 0; m < columns - 1; m++) {
                        if (m == j)
                            flagj = 1;
                        dop_matr.matrix[n][m] = matrix[n + flagi][m + flagj];
                    }
                }
                obratn_matr.matrix[j][i] = pow(-1, (i + j)) * dop_matr.opredelitel() * (1 / opred);
            }
        }
        cout << endl;
        return obratn_matr;
    }

    float** matrix;
    PlaceForMatrix Place = PlaceForMatrix::None;
    unsigned int columns, lines = 0;
};

Файл Types.h:

#pragma once

enum class PlaceForMatrix : int
{
    None,
    Console,
    File
};

Файл c main(он же HomeworkFor1-2Module.cpp):

#include <iostream>
#include <vector>
#include "MatrixClass.h"

using namespace std;

int main()
{
    int s = 2;
    (MatrixClass<float>::ZeroMatrix(s, s)).ShowMatrix();
    (MatrixClass<float>::ASingleMatrix(s, s)).ShowMatrix();

    cout << "Add elements: " << endl;
    MatrixClass<float> ParamMat(s, s);
    ParamMat.InitializeMatrixFromConsole();
    ParamMat.ShowMatrix();
    ParamMat.ShowMatrix((!ParamMat).matrix, s, s);

    cout << "FirstMatrix:" << endl;
    MatrixClass<float> MatrixFromFile(PlaceForMatrix::File);
    char FirstFilePath[] = "C:\\Users\\PC\\Desktop\\Лабы\\Программ\\Дз\\ReadMe.txt";
    MatrixFromFile.ReadMatrixFromFile(FirstFilePath);
    MatrixFromFile.ShowMatrix();

    cout << "SecondMatrix:" << endl;
    MatrixClass<float> TestMat(PlaceForMatrix::File);
    char SecondFilePath[] = "C:\\Users\\PC\\Desktop\\Лабы\\Программ\\Дз\\ReadMeAgain.txt";
    TestMat.ReadMatrixFromFile(SecondFilePath);
    TestMat.ShowMatrix();

    ParamMat = TestMat;
    ParamMat.ShowMatrix();


    cout << "FirstMatrix == 2?:";
    if (MatrixFromFile == 2)
        cout << " Yes" << endl;
    else
        cout << " No" << endl;

    cout << "FirstMatrix == SecondMatrix?:";
    if (MatrixFromFile == TestMat)
        cout << " Yes" << endl;
    else
        cout << " No" << endl;

    cout << "FirstMatrix != SecondMatrix?:";
    if (MatrixFromFile != TestMat)
        cout << " Yes" << endl;
    else
        cout << " No" << endl;

    return 0;
}

Буду очень благодарен если поможете.


Ответы (1 шт):

Автор решения: Harry
void operator=(MatrixClass &Matrix)
{
    matrix = Matrix.matrix;
    columns = Matrix.columns;
    lines = Matrix.lines;
}

При таком присваивании вы получаете:

  1. Утечку памяти (выделенная память не освобождена)
  2. Поверхностное копирование (копируете указатели, а не содержимое).

Результат: при присваивании образуется два указателя на одну область памяти. Которая будет освобождена в одном деструкторе, а потом во втором. Повторное освобождение уже освобожденной памяти это UB.

P.S. Все остальное не смотрел, так что не знаю, единственная ли это проблема или нет.

→ Ссылка