2017-10-28 40 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