2015-03-16 4 views
-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; 
} 

Когда я пытаюсь сделать две матрицы в главном, где измерение первого меньше, чем второе, происходит двойное свободное. Когда обе матрицы имеют одинаковую размерность, или размерность первой матрицы выше второй, нет проблем. Может быть, кто-то может увидеть код и рассказать мне, в чем проблема?Двойная свобода или коррупция - почему?

Edit: 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; 
} 
+0

Вы переступил с отладчиком? Это точно покажет вам, почему существует двойная свобода. Вам также не нужно проверять значение null перед удалением чего-либо. – chris

+3

Строка 'if (wsk! = 0) delete [] wsk;' внутри конструктора копирования не имеет смысла. Объект не существовал до того, как конструктор копирования начал выполняться, поэтому 'wsk' не может иметь значение, которое стоит проверить. – fredoverflow

+3

Шаг 1: Замените свой 'int *' на 'std :: vector ' Шаг 2: Прибыль – CoryKramer

ответ

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 или delete[]. Так что ваш деструктор может быть просто так:

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

Edit: Вы делаете это в main функции:

mac.~matrix();

Вы явный вызов деструктора. Итак, что происходит, когда объект mac выходит за рамки? Деструктор будет вызван снова, автоматически, таким образом, вы получите ошибку двойного удаления.

Удалить эту линию с main. Деструктор объекта будет вызываться автоматически.

+0

Это не помогло. Это все та же проблема. – oszust002

+0

Я не спрашивал об операторе =. Моя единственная и одна проблема заключается в том, что у меня есть двойной свободный от ниоткуда. Я удалил строку в конструкторе копирования и удалил operator =, потому что теперь это не важно. Проблема в том, почему после «cin >> matrix1», где я ставил, например, n = 2 и числа в нем, а затем «cin >> matrix2» и помещал более высокую размерность для примера n = 3, почему я получаю double free? – oszust002

+1

@KamilOsuch Пожалуйста, разместите главную() программу, которая дублирует ошибку. Вы никогда не публиковали, как вы тестируете этот класс. На самом деле вы не опубликовали код, показывающий, как вы на самом деле создаете один из этих «матричных» объектов. Все, что вы разместили, было конструктором по умолчанию и конструктором копирования. – PaulMcKenzie

0

Мне кажется, что delete [] пытается вызвать деструктор для каждого элемента массива, тогда он уничтожает указатель. Это может привести к двойной ошибке.

Вы пытались заменить

int *foo=new int[n*m] 

со старым C таНос?

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

Таким образом, вы можете использовать delete вместо delete []. Надеюсь, это сработает.

Удачи и дайте мне знать

гс

Смежные вопросы