C ++内存访问错误

时间:2014-10-03 17:58:41

标签: c++ memory

我在尝试调用函数Organization :: addWorker时遇到问题,它似乎在内存释放步骤失败,操作符删除[],但内存已经被释放,指针显示为。< / p>

调用堆栈:

  

lab1.exe!Person :: setName(char * thename)第80行C ++

     

lab1.exe!Coworker :: operator =(Coworker&amp; theco)Line 303 C ++

     

lab1.exe!Organization :: addWorker(Coworker&amp; the worker)404行C ++

     

lab1.exe!main()第97行C ++

   #include <string>
    #include "class_Date.h"

    using namespace std;

    enum workNec { worker, manager, employer };

    class Person {

        char* name; 
        char* surname;
        Date bd;

    public:

        Person();
        Person(char* thename, char* thesurname, Date thebd);
        Person(const Person &theperson);
        ~Person();

        char* getName() { return name; }
        char* getSurname() { return surname; }
        Date getBD() { return bd; }

        void getFullInfo();

        Person & setName(char* thename);
        Person & setSurname(char* thesurname);
        Person & setBD(int dd, int mm, int yy);
        Person & setBD(Date thebd);

        Person & operator=(Person& thepers);

    };

    Person::Person() { 

        name = new char [1];
        strcpy(name, "");
        surname = new char[1];
        strcpy(surname, "");

    }

    Person::Person(char* thename, char* thesurname, Date thebd) { 

        name = new char [strlen(thename)+1];
        surname = new char [strlen(thesurname)+1];
        strcpy(name, thename);
        strcpy(surname, thesurname);
        bd = thebd;

    }
    Person::Person(const Person & theperson) { 

        name = new char[strlen(theperson.name) + 1];
        surname = new char[strlen(theperson.surname) + 1];
        strcpy(name, theperson.name);
        strcpy(surname, theperson.surname);
        bd = theperson.bd;

    }
    Person::~Person() {

        cout << "Destructing Person " << name << endl;
        delete [] name;
        delete [] surname;


    }

    void Person::getFullInfo() { 

        cout << name << " " << surname << " "; bd.getFullDate(); 

    }

    Person & Person::setName(char* thename)  { 

        delete [] name;
        name = new char[strlen(thename) + 1]; strcpy(name, thename); 
        return *this; 

    }

    Person & Person::setSurname(char* thesurname) { 

        delete [] surname;
        surname = new char[strlen(thesurname) + 1]; strcpy(surname, thesurname);
        return *this; 

    }
    Person & Person::setBD(int dd, int mm, int yy) { 

        bd.setDD(dd); bd.setMM(mm); bd.setYY(yy); 
        return *this; 

    }

    Person & Person::setBD(Date thebd) { 

        bd = thebd; 
        return *this; 

    }

    Person & Person::operator=(Person& thepers) {

        delete [] this->name;
        delete [] this->surname;
        this->name = new char[strlen(thepers.name) + 1];
        this->surname = new char[strlen(thepers.surname) + 1];
        strcpy(this->name, thepers.name);
        strcpy(this->surname, thepers.surname);
        bd = thepers.bd;
        return *this;
    }

    //*************************************************************************************************

    class Position {

        char* department;
        workNec wn;
        int salary;

    public:

        Position();
        Position(char *thedept, workNec thewn, int thesalary);
        Position(const Position & thepos);
        ~Position();

        char* getDept() { return department; }
        workNec getWorkNec() { return wn; }
        int getSalary() { return salary; }

        void getFullInfo();

        Position & setDept(char* dept);
        Position & setWorkNec(workNec nec);
        Position & setSalary(int sal);

    };


    Position::Position() {

        department = new char[1];
        strcpy(department, "");

    }

    Position::Position(char *thedept, workNec thewn, int thesalary) { 

        department = new char[strlen(thedept) + 1];
        strcpy(department, thedept);
        wn = thewn; 
        salary = thesalary; 

    }

    Position::Position(const Position & thepos) { 

        department = new char[strlen(thepos.department)+1]; 
        strcpy(department, thepos.department);
        wn = thepos.wn; 
        salary = thepos.salary; 

    }

    Position::~Position() { 

        cout << endl << "Deleting Position " << department << endl;
        delete [] department;

    }

    void Position::getFullInfo() { 

        cout << department << " " << wn << " " << salary << " "; 

    }

    Position & Position::setDept(char* dept) { 

        delete [] department;
        department = new char[strlen(dept)+1];
        strcpy(department, dept);
        return *this; 

    }
    Position & Position::setWorkNec(workNec nec) {

        wn = nec; 
        return *this; 

    }
    Position & Position::setSalary(int sal) { 

        salary = sal; 
        return *this; 

    }

    //*************************************************************************************************

    class Coworker {

        Person person;
        Position position;

    public:

        Coworker();
        Coworker(Person &theperson, Position &thepos);
        Coworker( Coworker & theco);
        ~Coworker();

        Person getPerson() { return person; }
        Position getPosition() { return position; }

        void getFullInfo();

        Coworker & setPerson(Person &per);
        Coworker & setPosition(Position &pos);

        Coworker & operator=(Coworker& theco);

    };

    Coworker::Coworker() {

    }

    Coworker::Coworker(Person &theperson, Position &thepos) { 

        person.setBD(theperson.getBD());
        person.setName(theperson.getName());
        person.setSurname(theperson.getSurname());
        position.setDept(thepos.getDept());
        position.setSalary(thepos.getSalary());
        position.setWorkNec(thepos.getWorkNec());

    }

    Coworker::Coworker(Coworker & theco) { 

        Person pers;
        pers = theco.person;
        Position pos = theco.position;

        person.setBD(pers.getBD());
        person.setName(pers.getName());
        person.setSurname(pers.getSurname());
        position.setDept(pos.getDept());
        position.setSalary(pos.getSalary());
        position.setWorkNec(pos.getWorkNec());

    }

    Coworker::~Coworker() {


        cout << endl << "Deleting Coworker " << endl;

    }

    void Coworker::getFullInfo() { 

        person.getFullInfo(); cout << " ";  position.getFullInfo(); 

    }

    Coworker & Coworker::setPerson(Person &per) { 

        Person tper = per;
        person.setBD(tper.getBD());
        person.setName(tper.getName());
        person.setSurname(tper.getSurname());
        return *this; 

    }
    Coworker & Coworker::setPosition(Position &pos) { 

        Position tpos = pos;
        position.setDept(tpos.getDept());
        position.setSalary(tpos.getSalary());
        position.setWorkNec(tpos.getWorkNec());
        return *this; 

    }

    Coworker & Coworker::operator=(Coworker& theco) {

        Person pers;
        pers = theco.person;
        Position pos;
        pos = theco.position;

        person.setBD(pers.getBD());
        person.setName(pers.getName());
        person.setSurname(pers.getSurname());
        position.setDept(pos.getDept());
        position.setSalary(pos.getSalary());
        position.setWorkNec(pos.getWorkNec());
        return *this;
    }

    class Organization {

        char* title;
        Coworker * coworker;
        int cwAmount;

    public:

        Organization();
        Organization(char* thetitle, Coworker * theco, int thecw);
        Organization(const Organization & org);
        ~Organization();

        void addWorker(Coworker &theworker);

        char* getTitle() { return title; }
        int getAmount() { return cwAmount; }
        Coworker * getCoworker() { return coworker; }

        Organization & setTitle(char* tit);
        Organization & setAmount(int am);
        Organization & setCoworker(Coworker *theco);

        void getFullInfo();
        void getShortInfo();

    };

    //*************************************************************************************************

    Organization::Organization() {

        title = new char[1];
        strcpy(title, "");
        cwAmount = 0;
        coworker = new Coworker[0];

    }


    Organization::Organization(char* thetitle, Coworker * theco, int thecw) { 

        title = new char[strlen(thetitle) + 1];
        strcpy(title, thetitle);

        cwAmount = thecw; 
        coworker = new Coworker[cwAmount];

        for (int i = 0; i < cwAmount; i++) {

            coworker[i].setPerson(theco[i].getPerson());
            coworker[i].setPosition(theco[i].getPosition());

        }

    }

    Organization::Organization(const Organization & org) { 

        title = new char[strlen(org.title) + 1];
        strcpy(title, org.title);

        cwAmount = org.cwAmount; 

        coworker = new Coworker[cwAmount];

        for (int i = 0; i < cwAmount; i++) {

            coworker[i].setPerson(org.coworker[i].getPerson());
            coworker[i].setPosition(org.coworker[i].getPosition());

        }

    }

    Organization::~Organization() { 


        cout << endl << "Deleting Organization " <<title<< endl;
        delete [] coworker;

    };

    void Organization::addWorker(Coworker &theworker) {
        cout << "a";

        Coworker * new_coworker = new Coworker[cwAmount + 1];

        for (int i = 0; i < cwAmount; i++) new_coworker[i] = coworker[i];

        cwAmount++;

        new_coworker[cwAmount] = theworker;

        delete [] coworker;

        coworker = new_coworker;

    }

    void Organization::getFullInfo() {

        std::cout << title << " " << cwAmount << endl;
        for (int i = 0; i < cwAmount; i++) {
            coworker[i].getPerson().getFullInfo();
            cout << " ";
            coworker[i].getPosition().getFullInfo();
            cout << endl;
        }

    }

    void Organization::getShortInfo() {

        int total = 0;
        for (int i = 0; i < cwAmount; i++) {

            total += coworker[i].getPosition().getSalary();

        }

        std::cout << this->title << " " << total << std::endl;

    }

    Organization & Organization::setTitle(char* tit) { 

        title = new char[strlen(tit)+1]; 
        strcpy(title, tit);
        return *this; 

    }

    Organization & Organization::setAmount(int am) { 

        cwAmount = am; 
        return *this; 
    }

    Organization & Organization::setCoworker(Coworker *theco) { 

        delete [] coworker;
        coworker = new Coworker [cwAmount];

        for (int i = 0; i < cwAmount; i++) {

            coworker[i].setPerson(theco[i].getPerson());
            coworker[i].setPosition(theco[i].getPosition());

        }

        return *this; 

    }

main.cpp中:

#define _CRT_SECURE_NO_WARNINGS

#include "classes_v23.h"

using namespace std;

int main() {
    {
    Date d1;

    Date d2(19, 04, 1995);

    Date d3 = d2;

    d1.getFullDate(); cout << endl;
    d2.getFullDate(); cout << endl;
    d3.getFullDate(); cout << endl;

    //******************************

    Person pers1;

    pers1.setBD(d2);
    pers1.setName("Ihor");
    pers1.setSurname("Pukish");

    Person pers2("name2", "surname2", d2);
    Person pers3 = pers2;

    pers1.getFullInfo(); cout << endl;
    pers2.getFullInfo(); cout << endl;
    pers3.getFullInfo(); cout << endl;

    //******************************

    Position pos1;

    pos1.setDept("IASA");
    pos1.setSalary(100);
    pos1.setWorkNec(employer);

    Position pos2("dept2", worker, 200);
    Position pos3 = pos2;

    pos1.getFullInfo(); cout << endl;
    pos2.getFullInfo(); cout << endl;
    pos3.getFullInfo(); cout << endl;

    //******************************

    Coworker co1;
    co1.setPerson(pers1);
    co1.setPosition(pos1);

    Coworker co2(pers2, pos2);
    Coworker co3 = co2;
    Coworker co4(pers1, pos1);

    co1.getFullInfo(); cout << endl;
    co2.getFullInfo(); cout << endl;
    co3.getFullInfo(); cout << endl;

    //******************************

    Coworker * cow = new Coworker[3];
    cow[0] = co1;
    cow[1] = co2;
    cow[2] = co3;

    Organization org1("title", cow, 3);
    org1.addWorker(co4);
}
system("pause");
}

2 个答案:

答案 0 :(得分:1)

我认为问题是:

void Organization::addWorker(Coworker &theworker) {
    cout << "a";

    Coworker * new_coworker = new Coworker[cwAmount + 1];

    for (int i = 0; i < cwAmount; i++) new_coworker[i] = coworker[i];

    cwAmount++;

    new_coworker[cwAmount] = theworker;

    delete [] coworker;

    coworker = new_coworker;

}

请注意,在分配cwAmount之前,您需要增加theworker。但是我认为你应该先分配,然后再增加。空元素位于预增量索引处。

使用矢量也可以更轻松地完成。

答案 1 :(得分:0)

首先,您加入<string>,但未能使用<string>提供的内容,即std::string。既然你说你必须使用C风格的字符串,那么正确的标题是<cstring>,而不是<string>

其次,如果传递NULL,甚至是伪造的指针,该函数将不起作用:

Person::Person(char* thename, char* thesurname, Date thebd) { 
        name = new char [strlen(thename)+1];   // undefined behavior if NULL is passed
        surname = new char [strlen(thesurname)+1];  // undefined behavior if NULL is passed
        //...
    }

该函数应检查NULL指针争论。但即便如此,存在传递指针的风险,该指针不指向有效的缓冲区。

现在,正如其他人所说,你需要正确编写赋值运算符,并为每个具有动态分配内存指针的类编写。

让我们从Person赋值运算符开始:

 Person & Person::operator=(Person& thepers) {
        delete [] this->name;
        delete [] this->surname;
        this->name = new char[strlen(thepers.name) + 1];
        this->surname = new char[strlen(thepers.surname) + 1];
        strcpy(this->name, thepers.name);
        strcpy(this->surname, thepers.surname);
        bd = thepers.bd;
        return *this;
    }

这不仅是多余的(大部分代码都在复制构造函数中),它失败的原因如下:

  1. delete[]姓名。如果以下new[]引发异常会发生什么?您可以通过删除数据来搞砸您的对象,然后才能确定新的数据不会失败。
  2. 你没有检查自我分配。
  3. 该项应作为const引用传递。
  4. 修复的方法很简单,我建议你为所有其他课程这样做。

     #include <algorithm>
     //...
     Person & Person::operator=(const Person& thepers) 
     {
          Person other(thepers);
          swap(*this, other);
          return *this;
     }
    
     void Person::swap(Person& left, Person& right)
     {
          std::swap(left.name, right.name);
          std::swap(left.surname, right.surname);
          std::swap(left.bd, right.bd);
      }
    

    那就是它,没有别的。这称为copy/swap成语。只要您编写了一个正确的复制构造函数,上面的代码不仅可以正确复制,还可以解决自我分配问题,并过早地破坏成员。

    它的工作方式是创建一个临时的&#34;窃取&#34;通过将你的临时工具换成你自己的临时工具,并将你的旧东西与临时骰子放在一起。外行人的说法就是正在发生的事情。

    请为其他课程执行此操作。例如,Coworker

    Coworker & Coworker::operator=(const Coworker& theco) 
    {
       Coworker temp(theco);
       swap(*this, temp);
       return *this;
    }
    
    void Coworker::swap(Coworker& left, Coworker& right)
    {
        std::swap(left.person, right.person);
        std::swap(left.position, right.position);
    }
    

    此外,您的Organization类缺少赋值运算符。只需使用上述技术添加一个。

    此外,您的setName函数在重新分配之前也会删除内存:

    Person & Person::setName(char* thename)  { 
        delete [] name;
        name = new char[strlen(thename) + 1]; strcpy(name, thename); 
        return *this; 
    }
    

    这也可以通过先分配一个临时值,然后再分配给它来缓解 在函数结束时临时:

    Person & Person::setName(char* thename)  
    { 
        char *tempname = new char[strlen(thename) + 1]; 
        strcpy(tempname, thename); 
        delete [] name;
        name = tempname;
        return *this;
    }