析构函数导致程序崩溃

Destructor causes the program to crash

本文关键字:崩溃 程序 析构函数      更新时间:2023-10-16

我真的在为将析构函数与复制构造函数一起使用的概念而苦苦挣扎。如果我不使用析构函数,代码可以正常工作,因为它会自动完成。如果我这样做,我会收到一个错误,说"调试断言失败!"和"表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)。

但我希望能够理解如何使用析构函数。这是下面的代码,我将非常感谢帮助解释我做错或需要做的事情!
类矩阵 {

private:
    int M;
    int N;
    double *data;
public:
    Matrix();
    int getM() const { return M; }
    int getN() const { return N; }
    //CONSTRUCTOR
    Matrix(int sizeR, int sizeC,double * input_data)
    {
        M = sizeR; //Rows
        N = sizeC; //Columns
        data = new double[M*N]; //creation of 1D array, uses m&n values
        cout << "nMatrix::Matrix(int sizeR, int sizeC, double * data_value) is invoked...nn";
        //ENTER DATA INTO MATRIX HERE:
        for(int i=0; i < M*N; i++) //Loops for every data entry into 1D array, uses r&c as referenece to
            data[i] = input_data[i];//Accesses each value at specific location, inputs value 'val'
        for(int i = 0; i < M*N; i++) //Loops for every data entry into 1D array, uses r&c as referenece to size
            cout << data[i] << " ";
    }
    //get function uses row and column from user
    double get(int i, int j)
    {
        return data[i*N+j];
    }
    double set(int i, int j, double val)
    {
        data[i*N+j] = val;
        cout << "nnNEW MATRIX: ";
        for(int i = 0; i < M*N; i++)//Loops for every data entry into 1D array, uses r&c as referenece to size
            cout << data[i] << " ";
        return val;
    }
    Matrix(const Matrix& oldMatrix)
    {
        cout¸<< "nMatrix::Matrix(const Matrix&) is invoked....";
        M = oldMatrix.getM();
        N = oldMatrix.getN();
        data = oldMatrix.data;
        cout << "nn";
        //ENTER DATA INTO MATRIX HERE:
        for(int i = 0; i < M*N; i++)//Loops for every data entry into 1D array, uses r&c as referenece to size
            cout << data[i] << " ";
    }
    //DESTRUCTOR
    ~Matrix()
    {
        //delete data
        delete [] data;
        data = NULL;
        cout << "nnMatrix::~Matrix() is invoked...nn";
    }

};
int main()
{
    int sizeR, sizeC;
    double val;
    cout << "Enter No. Rows: ";
    cin >> sizeR;
    cout << "Enter No. Columns: ";
    cin >> sizeC;
    double * input_data;

    input_data = new double[sizeR*sizeC];
    //INPUTS VALUES TO ARRAY
    for(int i = 0; i < sizeR*sizeC; i++)//Loops for every row
        input_data[i] = i;
    Matrix M1(sizeR, sizeC, input_data);
    cout << "Enter row that value you are after is in: ";
    cin >> sizeR;
    cout << " & now the column that it is in: ";
    cin >> sizeC;

    cout << "Change value: " << M1.get(sizeR, sizeC) << " to:";
    cin >> val;
    M1.set(sizeR, sizeC, val);
    //calls copy constructor
    M1 = Matrix(M1);
}

在复制构造函数中,你复制指针,这意味着你现在有两个对象都具有相同的指针。如果其中一个对象被销毁,则会使用现在无效的指针保留另一个对象。

无论如何取消引用此指针,或尝试释放它,都将导致未定义的行为

有问题的台词是这样的:

M1 = Matrix(M1);

该行创建一个临时对象,并将数据从M1复制到该临时对象中,然后将临时对象赋M1(编译器生成的复制赋值运算符将只执行成员的浅拷贝,因此与您的复制构造函数没有太大区别),然后销毁临时对象,导致M1中的杂散和无效指针。


在一个稍微相关的问题上,您可能还想了解三法则。

您正在将一个对象的指针复制到 Copy 构造函数中的另一个对象中:

Matrix(const Matrix& oldMatrix)
{
   ...
   data = oldMatrix.data;

调用复制构造函数后,您有两个对象引用同一个内存块。如果一个对象被销毁,则内存块将被删除,第二个对象指向无效的内存位置。

在复制构造函数中,您还需要分配一个新的缓冲区!

解决方案可能是将布尔变量(例如is_copy)添加到矩阵类中。 在构造函数上将其设置为 false,在复制构造函数上将其设置为 true。仅当析构函数中的内存is_copy为 false 时才释放内存。

或者,正如评论中所建议的,最好使用智能指针。