双重免费或腐败 - 为什么?

时间:2015-03-16 17:15:54

标签: c++ matrix cout cin double-free

class matrix{
    private:
        int n, *wsk;
        friend istream & operator>>(istream&,matrix&);
        friend ostream & operator<<(ostream&,matrix&);
    public:
        matrix(){
            wsk=0;
            n=0;        
        }
        matrix(const matrix &mat){
            this->n=mat.n;
            if (wsk!=0) delete []wsk;
            this->wsk=new int [this->n*this->n];
            for (int i=0;i<n*n;i++)
                wsk[i]=mat.wsk[i];

        }

        ~matrix(){
            if (this->wsk!=0) delete[]this->wsk;
        }

        const matrix & operator=(const matrix &mat){
            if(&mat==this) return *this;
            if (this->wsk!=0) delete [] this->wsk;
            n=mat.n;
            this->wsk=new int [n*n];
            for (int i=0;i<mat.n*mat.n;i++)
                this->wsk[i]=mat.wsk[i];
            return *this;   
    } 
};


istream & operator>>(istream &str, matrix& mat){

    str >> mat.n;
    if (mat.n>0) {
        if (mat.wsk != 0) delete[]mat.wsk;
        mat.wsk= new int [mat.n*mat.n];
        for (int i=0;i<mat.n*mat.n;i++)
            str >> mat.wsk[i];
    }

    return str;
}

ostream & operator<<(ostream &str, matrix& mat){
    if (mat.wsk!=0){
        for (int i=0;i<mat.n*mat.n;i++){
            str << mat.wsk[i] << " ";
            if ((i+1)%mat.n==0) str << endl;
        }
    }
    return str;
}

当我试图在main中制作两个矩阵时,第一个维度低于第二个矩阵,正在发生双重自由。当两个矩阵具有相同的维度,或者第一矩阵的维度高于第二矩阵时,没有问题。也许有人可以看到代码并告诉我这是什么问题?

编辑:主要:

int main(){
    matrix mac, a, b;
    cout << "Put number of dimensions and numbers in matrix ";  
    cin >> mac;
    cout << mac;
    cin >> a;   
    cout << a;
    mac.~matrix();
    return 0;
}

2 个答案:

答案 0 :(得分:2)

我看到的一个错误是,在复制构造函数中,您正在删除从未分配的内存:

 this->n=mat.n;
 if (wsk!=0) delete []wsk;

检查非NULL对您没有帮助。该指针可能具有非空垃圾值,并且您使用垃圾指针调用delete[]。只需从复制构造函数中删除该行。

其次,您的赋值运算符存在问题:

  const matrix & operator=(const matrix &mat){
            if(&mat==this) return *this;

            // you've destroyed your data here
            if (this->wsk!=0) delete [] this->wsk;

            // you've changed one of your members here
            n=mat.n;

            // what if the line below throws a `std::bad_alloc` exception?
            this->wsk=new int [n*n];

评论解释了这个问题。您删除了自己的数据,如果new[]稍后失败,则无法恢复。

您还会返回const。对于赋值运算符返回const对象,这是非常规的。

编写赋值运算符的更好方法是:

  #include <algorithm>
  //...
  matrix & operator=(matrix mat)
  {
     std::swap(n, mat.n);
     std::swap(wsk, mat.wsk);
     return *this;
  }

在给定工作副本构造函数和析构函数的情况下,这可以保证工作。这里使用copy/swap成语。

此外,在发出deletedelete[]时无需检查空指针。所以你的析构函数就是这样:

~matrix(){ delete[]this->wsk; }

编辑:您正在main函数中执行此操作:

mac.~matrix();

您正在显式调用析构函数。那么当mac对象超出范围时会发生什么?将自动再次调用析构函数,因此您将获得双删除错误。

main删除此行。将自动调用对象的析构函数。

答案 1 :(得分:0)

对我来说,似乎delete []尝试为数组的每个元素调用析构函数,然后它会销毁指针。它可能会导致双重自由错误。

您是否尝试过更换

int *foo=new int[n*m]

旧C malloc?

int *foo;
foo=(int*)malloc(n*m*sizeof(int));

这样你可以使用delete而不是delete []。我希望这有效。

玩得开心,让我知道

GF