2017-10-28 76 views
0

我已經完成了這個程序,我檢查我的'日期'類是否正確。問題是,當我運行我的測試程序,它返回我以下錯誤:我正在釋放內存兩次 - C++

  • 錯誤`./bin/test「:雙重釋放或腐敗(fasttop):0x00000000019c07c0 *

這個類的工作是讀取和存儲'日期'(一年)和一些事件(分配在字符串數組中)。例如,這個類的一個對象是:1998 EVENT1 EVENT2 EVENT3。

操作>>讀取下一格式:1908#Fantasmagorie#馴悍記#的偷竊手#馴服吉斯#A參觀公爵的海邊

好刺殺,我的問題是,我刪除某些指針兩次或釋放一些內存兩次,我已經嘗試了很多東西,但我不知道如何解決它(正如你可以看到我的代碼,我已經試圖設置所有指針爲0時,我刪除): Date類的.h

#ifndef _date_HISTORICA_ 
#define _date_HISTORICA_ 

#include <iostream> 
#include <string> 
#include <cassert> 

using namespace std; 

class date{ 
private: 
    int year; 
    int eventsNum; 
    int reserved; 
    string * str; 
    void resize(int r); 
public: 
    date(); 
    //date(int a, string *s, int n); 
    date(const date& d); 
    ~date(); 
    int getAge(); 
    void addEvent(string& s); 
    friend ostream& operator<<(ostream& os, const date& d); 
    friend istream& operator>>(istream& is, date& d); 
}; 



#endif 

日期類代碼:

#include<iostream> 
#include<string> 
#include<fstream> 
#include<sstream> 
#include<date.h> 

using namespace std; 

void date::resize(int r) 
{ 
    assert(r>=0); 
    if(r!=this->reserved) 
    { 
    if(r!=0) 
    { 
     string * aux = new string[r]; 
     if(this->reserved>0) 
     { 
      int min=this->reserved<r?this->reserved:r; 
      for(int i=0; i<min; i++) 
       aux[i]=this->str[i]; 
      delete[] this->str; 
      this->str=NULL; 
     } 
     this->str=aux; 
     this->reserved=r; 
     if(this->reserved<this->eventsNum) 
      this->eventsNum=this->reserved; 
    } else 
    { 
     if(this->reserved>0) 
     { 
      delete[] this->str; 
      this->str=NULL; 
     } 
     this->year=0; 
     this->eventsNum=0; 
     this->reserved=0; 
    } 
    } 
} 

date::date() : year(0), eventsNum(0), reserved(0), str(0){} 

date::date(const date& d) 
{ 
    this->year=d.year; 
    this->eventsNum=d.eventsNum; 
    this->reserved=d.reserved; 
    this->str=new string[this->reserved]; 
    for(int i=0; i<this->eventsNum; i++) 
     this->str[i]=d.str[i]; 
} 

date::~date() 
{ 
    this->year=0; 
    this->eventsNum=0; 
    this->reserved=0; 
    if(this->str) 
    delete[] this->str; 
    this->str=NULL; 
} 

int date::getAge(){return this->year;} 

ostream& operator<<(ostream& os, const date& d) 
{ 
    os << d.year; 
    for(int i=0; i<d.eventsNum; i++) 
     os << '#' << d.str[i]; 
    os << endl; 
    return os; 
} 

void date::addEvent(string& s){ 
    if (this->eventsNum == this->reserved){ 
     if (this->eventsNum==0) 
      resize(1); 
     else 
      resize(2*this->reserved); 
    } 
    this->str[eventsNum]=s; 
    eventsNum++; 
} 

istream& operator>>(istream& is, date& d) 
{ 
    string line; char c; 
    is >> d.year >> c; 
    getline(is, line); 

    int n=1; 
    for(int i=0; i<line.length(); i++) 
     if(line[i]=='#') 
      n++; 

    d.eventsNum=n; 
    d.reserved=d.eventsNum; 
    delete[] d.str; 
    d.str=NULL; 
    d.str=new string[n]; 

    stringstream ss(line); 

    for(int i=0; i<n; i++) 
     getline(ss, d.str[i], '#'); 
    return is; 
} 

測試程序類別:

#include<iostream> 
#include<fstream> 
#include<cronologia.h> 
#include<date.h> 

using namespace std; 

int main(int argc, char * argv[]){ 
    cout << "STATE: IN PROGRESS" << endl; 
    cout << "TEST: (2)" << endl; 
    date d; 

    ifstream f("./data/name.txt"); 

    while(f >> d) 
    { 
     cout << d; 
    } 
    date d1; 
    cin >> d1; 
    d=d1; 
    cout << d << endl; 


} 

示例文件(至極應該按日期CLAS讀):

1900#Sherlock Holmes Baffled#The Enchanted Drawing 
1901#Star Theatre#Scrooge, or, Marley's Ghost 
1902#A Trip to the Moon 
1903#The Great Train Robbery#Life of an American Fireman 
1904#The Impossible Voyage 
1905#Adventures of Sherlock Holmes; or, Held for Ransom 
1906#The Story of the Kelly Gang#Humorous Phases of Funny Faces#Dream of a Rarebit Fiend 
1907#Ben Hur#L'Enfant prodigue 
1908#Fantasmagorie#The Taming of the Shrew#The Thieving Hand#The Assassination of the Duke of Guise#A Visit to the Seaside 

林,我的英語很抱歉! :(

+3

字符'D = D1;'=哪裏是你的重載賦值操作符和拷貝構造函數?你可能會發現這是一個有趣的讀法:[The Three/Five/Zero](http://en.cppreference.com/w/cpp/language/rule_of_three) – WhozCraig

+0

重載賦值操作符和拷貝構造函數已經完成。我將添加.h文件,以便您可以更好地看到它們。 –

+0

這將有所幫助。沒有他們,懷疑是真正的複製。 – WhozCraig

回答

3

由於沒有分配代碼中的超載,在該行

d=d1; 

所有的d1成員將由值被複制到一個新的對象d因此會有兩個副本對象date在它們的成員str中具有相同的參考值,這兩個將最終超出範圍並且將被破壞,第一個將釋放分配的內存,而另一個將嘗試釋放相同的引用,這就是爲什麼你得到錯誤。

-1

你需要一個拷貝賦值運算符:

void swap(date& other) 
{ 
    using std::swap; 
    swap(year, other.year); 
    swap(eventsNum, other.eventsNum); 
    swap(reserved, other.reserved); 
    swap(str, other.str); 
} 

date::date(const date& d) : year(other.year), eventsNum(other.eventsNum), reserved(other.reserved), str(new string[other.reserved]) 
{ 
    for(int i = 0; i < this->eventsNum; i++) 
     this->str[i] = d.str[i]; 
} 

date& date::operator = (const date& d) 
{ 
    swap(*this, d); 
    return *this; 
} 

也可能是不錯的提供移動構造函數..

+0

此實現不是異常安全的,會產生內存泄漏,並且不能正確處理自賦值。應該使用複製和交換。 –

+0

如果'this'分配了字符串,則會泄漏內存。 – Ivan

+1

不正確的實現...複製構造函數需要直接實現。然後可以使用coy構造函數和swap來實現賦值運算符。我建議您在Herb Sutter的** Exceptional C++ **書中再次閱讀**第13項**。 – Phil1970