尝试创建动态分配的char数组时出现分段错误

时间:2018-03-23 16:46:41

标签: c++

这是我的代码:

#include<iostream>
#include<string.h>
using namespace std;

class Zichara
{
    private:
        char *name;
        int price;

    void copy(const Zichara &from)
    {
        name = new char[strlen(from.name) + 1];
        strcpy(name, from.name);
        price = from.price;
    }
    public:
        Zichara(const char *name, int price) {
            this->name = new char[strlen(name) + 1];
            strcpy(this->name, name);
            this->price = price;
        }
    Zichara(const Zichara &from)
    {
        copy(from);
    }
    ~Zichara() {
        delete [] name;
    }

    friend class PlaninarskiDom;
};

class PlaninarskiDom {
private:
    char name[15];
    int prices[2];
    char star;
    bool isZichara;
    Zichara *zich;
    void copy(const PlaninarskiDom &from) {
        strcpy(name, from.name);
        star = from.star;
        isZichara = from.isZichara;
        zich = from.zich;
        for(int i = 0; i < 2; i++) {
            prices[i] = from.prices[i];
        }
    }

public:
    PlaninarskiDom(const char *name = "", int prices = 0, const char star = '\0') {
        strcpy(this->name, name);
        this->star = star;
        isZichara = 0;
        zich = 0;
        this->prices[0] = 0;
        this->prices[1] = 0;
    }
    PlaninarskiDom(const char *name, int *prices, const char star) {
        strcpy(this->name, name);
        this->star = star;
        isZichara = 0;
        zich = 0;
        this->prices[0] = prices[0];
        this->prices[1] = prices[1];
    }
    PlaninarskiDom(const PlaninarskiDom &from) {
        copy(from);
    }
    ~PlaninarskiDom() {
        delete [] zich;
    }

    PlaninarskiDom& operator = (const PlaninarskiDom &from) {
        if(this == &from) return *this;
        delete [] zich;
        copy(from);
        return *this;
    }

    void setZichara(Zichara &z) {
        if(isZichara == 0) {
            zich->copy(z);
            isZichara = 1;
        }
    }

    void operator --() {
        if((int)star >= 65 && (int)star <= 70) {
            ++star;
            if((int)star == 69) {
                ++star;
            }
        }
    }

    bool operator <= (char c) {
        return star >= c;
    }

    void presmetajDnevenPrestoj(int day, int month, int &price) {
        if(day < 0 || day > 31 || month < 0 || month > 12) {
            throw 99;
        }
        else if(month >= 4 && month <= 8) {
            price = prices[0];
        }
        else {
            price = prices[1];
        }
        if(isZichara) {
            price += zich->price;
        }
    }

    friend ostream& operator << (ostream &, const PlaninarskiDom &);
};

ostream& operator << (ostream &os, const PlaninarskiDom &rhs) {
    cout << rhs.name << " klasa:" << rhs.star << endl;
    if(rhs.isZichara) {
        cout << " so zichara" << endl;
    }
    return os;
}

int main(){

    PlaninarskiDom p; //креирање на нов објект од класата планинарски дом

    //во следниот дел се вчитуваат информации за планинарскиот дом
    char imePlaninarskiDom[15],mestoZichara[30],klasa;
    int ceni[12];
    int dnevnakartaZichara;
    bool daliZichara;
    cin>>imePlaninarskiDom;
    for (int i=0;i<2;i++) cin>>ceni[i];
    cin>>klasa;
    cin>>daliZichara;

    //во следниот дел се внесуваат информации и за жичарата ако постои
    if (daliZichara) {
        cin>>mestoZichara>>dnevnakartaZichara;
        PlaninarskiDom pom(imePlaninarskiDom,ceni,klasa);
        Zichara r(mestoZichara,dnevnakartaZichara);
        pom.setZichara(r);
        p=pom;
    }
    else{
        PlaninarskiDom *pok=new PlaninarskiDom(imePlaninarskiDom,ceni,klasa);
        p=*pok;
    }

    //се намалува класата на планинарскиот дом за 2
    --p;
    --p;

    int cena;
    int den,mesec;
    cin>>den>>mesec;
    try{
        p.presmetajDnevenPrestoj(den,mesec,cena); //тука се користи функцијата presmetajDnevenPrestoj
        cout<<"Informacii za PlaninarskiDomot:"<<endl;
        cout<<p;
        if (p<='D')
            cout<<"Planinarskiot dom za koj se vneseni informaciite ima klasa poniska ili ista so D\n";

        cout<<"Cenata za "<<den<<"."<<mesec<<" e "<<cena; //се печати цената за дадениот ден и месец
    }
    catch (int){
        cout<<"Mesecot ili denot e greshno vnesen!";
    }
}

我在这段代码上运行了一个调试器,它强调了这一点:

 name = new char[strlen(from.name) + 1];

这是代码行作为Seg Fault来自的行。

这是我的课程练习,我必须使用动态内存分配 我之前已多次完成同样的事情而且没有这样的错误,所以我不知道它为什么会出现,到目前为止我无法在Google上找到这个问题的答案,所以我如果某处存在,那就道歉。

感谢大家的建议,这已得到修复!

1 个答案:

答案 0 :(得分:1)

你称之为这个方法:

void setZichara(Zichara &z) {
    if(isZichara == 0) {
        zich->copy(z);
        isZichara = 1;
    }
}

但你永远不会分配zich所以你调用UB调用nullptr上的方法

注意:你的PlaninarskiDom::copy()也是不正确的,因为你只是从另一个对象(也就是浅拷贝)分配指针,这将导致多次破坏,尽管很可能你还没有遇到这个问题。您应该进行深层复制或使用std::shared_ptr您是否计划共享所有权。无论如何,如果您不受使用智能指针的条件限制,在处理动态分配的对象时更可取。或者使用std::vectorstd::string之类的特殊容器为您做适当的内存管理。