C++ 不寻常的双重自由损坏错误(复制构造函数不起作用)

C++ Unusual double free corruption error (copy constructor doesn't work)

我是一名学生,我被要求 "replicate"(有点)矢量 class。显然,臭名昭著的 "double free corruption" 发生了。三个规则我一直在思考(可能不太好),我找不到错误。

Vettore.h

#ifndef vettore_h_
#define vettore_h_

#include <iostream>
#include <cmath>
#include <fstream>

class Vettore {

   protected:
      unsigned int _N;
      double * _v;
      void Quicksort(unsigned int primo, unsigned int ultimo);
      void Scambia (int a, int b);

   public:
      Vettore ();
      Vettore (int N);
      Vettore (int N, char* nomefile);
      Vettore (const Vettore& v);
      void SetComponent (int i, double x);
      void AddComponent (double x);
      double GetComponent (int i) const;
      void Print () const;
      void Print (char* nomefile) const;
      void Sort();
      int GetN() const;
      Vettore& operator=(const Vettore & vetty);
      ~Vettore();   
};

#endif

Vettore.c

#include "Vettore.h"

//Default Constructor

Vettore :: Vettore () {

   _N=0;
   _v=NULL;

};

//N Constructor

Vettore :: Vettore (int N) {

   _N=N;
   _v=new double [_N];

   for (int i=0; i<_N; i++)
      _v[i]=0;
};

//N file-taken constructor

Vettore :: Vettore (int N, char* nomefile) {

   _N=N;
   _v=new double [_N];

   std::ifstream input;
   input.open(nomefile);

   double dato;

   input>>dato;

   for(int i=0; i<N; i++){
      _v[i]=dato;
      input>>dato;
   };

   input.close();

};

//Copyconstructor

Vettore :: Vettore (const Vettore& V) {

   _N=V.GetN();

   _v=new double [_N];

   for(int i=0; i<_N; i++)
      _v[i]=V.GetComponent(i);


};

//Destructor

Vettore::~Vettore(){

   delete[] _v;

};

//Set Component

void Vettore :: SetComponent (int i, double x) {

   if (i>_N) {
      std::cout<<"errore!"<<std::endl;
      return ;
   };


   _v[i]=x;

};

//Get Component

double Vettore :: GetComponent (int i) const {

   if (i>_N){
      std::cout<<"errore!"<<std::endl;
      return 0;
   };

   return _v[i];
};

//Add Component 

void Vettore :: AddComponent (double x) {

   double* a=new double [_N+1];

   for(int i=0; i<_N; i++)
      a[i]=_v[i];

   a[_N]=x;

   _v=a;
   _N=_N+1;
   a=NULL;
   delete [] a;

};

//Print

void Vettore :: Print () const {

   std::cout<<"Il vettore ha: "<<_N<<" componenti."<<std::endl;

   for(int i=0; i<_N; i++)
      std::cout<<_v[i]<<std::endl;

};

//Print file

void Vettore :: Print (char* nomefile) const {
   std::ofstream output;
   output.open(nomefile);

   output<<_N;

   for(int i=0; i<_N; i++)
      output<<_v[i]<<std::endl;

   output.close();

};


//Get _N

int Vettore :: GetN () const {

   return _N;

};

//Operatore di Assegnazione

Vettore & Vettore::operator =(const Vettore& vetty){

   _N=vetty.GetN();
   _v=new double [_N];

   for(int n; n<_N; n++)
      _v[n]=vetty._v[n];

   return *this;
};



//Algoritmo Quicksort

void Vettore :: Sort (){
    Quicksort(0,GetN()-1);
};

void Vettore :: Quicksort (unsigned int primo, unsigned int ultimo) {

    if(ultimo-primo<=1){
       if (GetComponent(primo)>GetComponent(ultimo)) Scambia(primo, ultimo);
       return;
    }

    double pivot= GetComponent(int((primo+ultimo)/2));
    unsigned int basso= primo, alto=ultimo;
    while(basso < alto) {

        while (GetComponent(basso)<pivot) basso++;
        while (GetComponent(alto)>pivot) alto--;
        if(basso<alto) { Scambia(basso,alto); basso++;};
    };
    Quicksort(primo, basso-1);
    Quicksort(basso, ultimo);
};

void Vettore :: Scambia(int a, int b){

    double k;
    k=_v[a];
    _v[a]=_v[b];
    _v[b]=k;
};

主要例子

#include "Vettore.h"
#include <iostream>

using namespace std;

int main (int argv, char** argc) {

   Vettore A(10);

   Vettore B(10, argc[1]);

   Vettore C(B);

   C.SetComponent(2, 3);

   B.AddComponent(12.5);

   cout<<A.GetComponent(3)<<" "<<A.GetN()<<endl;

   B.Sort();

   B.Print();

   C.Print(argc[2]);

   A.~Vettore();
   B.~Vettore();
   C.~Vettore();

   return 0;
}

奇怪的是析构函数被调用了三次(我通过析构函数中的couts检查过);另一件奇怪的事情是我无法清楚地找到错误的来源,因为有时 AddComponent 给我带来问题(但并非总是如此),而 Copyconstructor 似乎总是给我带来问题(换句话说,如果我消除了初始化的 C 向量使用复制构造函数,它不会给我错误)。

A.~Vettore();
B.~Vettore();
C.~Vettore();

这就是您的错误来源。初学者很少(如果有的话)需要显式调用对象的析构函数。当对象 ABC 超出范围时,会自动调用析构函数。

在你的Add Component

_v=a;
_N=_N+1;
a=NULL;
delete [] a;

正确的实现方式是:

_N = _N + 1;
delete[] _v;
_v = a;

或者在调用对象的析构函数时,显式或隐式地删除_v两次