-1
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 中制作两个矩阵时,第一个维度低于第二个维度,就会发生 double free 。当两个矩阵的维数相同,或者第一个矩阵的维数高于第二个时,就没有问题。也许有人可以看到代码并告诉我有什么问题?

编辑:主要:

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;
}
4

2 回答 2

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使用成语。

delete此外,在发出or时无需检查空指针delete[]。所以你的析构函数可以简单地是这样的:

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

main编辑:你在你的函数中这样做:

mac.~matrix();

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

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

于 2015-03-16T17:21:50.740 回答
0

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

您是否尝试过更换

int *foo=new int[n*m]

与旧的 C malloc?

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

这样你就可以使用 delete 而不是 delete[]。我希望这行得通。

玩得开心,让我知道

女朋友

于 2015-03-16T17:57:41.230 回答