双重自由或腐败 - 为什么

Double free or corruption- why?

本文关键字:为什么 自由      更新时间:2023-10-16
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;
}

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

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

检查非 NULL 对您没有帮助。 该指针可能具有非 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中删除此行。 将自动调用对象的析构函数。

在我看来

,delete[] 试图为数组的每个元素调用析构函数,然后它破坏了指针。它可能会带来双重免费错误。

您是否尝试过更换

int *foo=new int[n*m]

用老C马洛克?

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

这样,您可以使用删除而不是删除[]。我希望这有效。

玩得开心,让我知道

格芯