为什么析构函数不释放数组内存?

时间:2017-01-10 14:09:55

标签: c++ valgrind destructor delete-operator

我的问题是为什么析构函数不释放我的临时数组的内存? Valgrind告诉我,我在构造函数中使用了new运算符,但之后没有删除内存。当我简单地写delete temp时,我在Valgrind中遇到了许多错误,例如无效读取大小,双重免费等等。你能告诉我们这些人在这里发生了什么吗?

array_xyz(const int r, const int c, double **arg_array) {

    rows = r;
    cols = c;
    array_xyz *temp = new array_xyz();
    temp->arr = new double *[rows];
    temp->rows = r;
    temp->cols = c;
    arr = new double *[rows];

    for (int i = 0; i < rows; i++) {
        arr[i] = new double [cols];
        temp->arr[i] = new double [cols];
    }

    for (int j = 0; j < rows; j++) {
        for (int k = 0; k < cols; k++)
            temp->arr[j][k] = arg_array[j][k];
    }

    arr = temp->arr;
    //delete temp; -> doesn't work, valgrind tells that I free memory twice
}

array_xyz() {
    rows = 0;
    cols = 0;
    arr = NULL;
}

~array_xyz() {
    for (int i = 0; i < rows; i++)
        delete []arr[i];
    delete []arr;
}

3 个答案:

答案 0 :(得分:5)

您同时分配arr(及其所有行)和temp_arr(及其所有行)。然后你做arr=temp_arr;。它不会将temp_arr的值复制到arr。相反,它会强制arr指向与temp_arr相同的地址。以前分配给arr的整个内存现在是孤立的(没有指向它的指针,所以你不能释放它,它没有用处)。如果您删除temp_arr,它会自动删除arr,因为它们现在指向内存中的相同位置。

答案 1 :(得分:2)

在此声明之后

arr = temp->arr;

两个指针arrtemp->arr指向相同的内存扩展。

如果您添加此声明

delete temp

然后类array_xyz的析构函数释放了这个内存范围(以及动态分配的数组的元素指向的范围)。此外,创建的对象的析构函数也将删除相同的内存范围,因为它自己的指针arr指向同一个内存。因此会尝试两次释放相同的内存范围。

目前尚不清楚为什么要使用指针temp指向的中间动态创建的对象。它完全是一个冗余的代码,只会混淆构造函数的读者。

答案 2 :(得分:1)

谢谢,我明白了。我想将值从arg_array复制到arr,好的一点是甚至不需要temp。

这是解决方案:

  array_xyz(const int r, const int c, double **arg_array) {

    rows = r;
    cols = c;
    arr = new double *[rows];

    for (int i = 0; i < rows; i++) {
        arr[i] = new double [cols];
    }

    for (int j = 0; j < rows; j++) {
        for (int k = 0; k < cols; k++)
            arr[j][k] = arg_array[j][k];
    }

}