访问冲突(分段错误)

时间:2013-10-19 01:53:50

标签: c++ arrays class object segmentation-fault

我有两个班级(约会,日程安排)和一个司机(主要)。

main.cpp中:

#include <iostream>
#include "schedule.h"
#include "appointment.h"

using namespace std;

int main()
{
    schedule mySch2("hello");

    appointment myAppt(100002,"appointment",10,1,2013);
    myAppt.printS(cout,2);

    mySch2.addtoSchedule(myAppt);


    system("PAUSE");
    return EXIT_SUCCESS;
}

schedule.h

#ifndef SCHEDULE_H
#define SCHEDULE_H

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

using namespace::std;
const int SCH_ENTRIES = 10;
class schedule
{
      public:
             schedule(void);
             schedule(const char *p);
             bool addtoSchedule(const appointment &);

      private:
              char title[40];
              int count;
              appointment appointmentArray[SCH_ENTRIES];
};
#endif

schedule.cpp

#include "schedule.h"
#include "appointment.h"
#include <iostream>

using namespace::std;

schedule::schedule(void)
{
}
schedule::schedule(const char *p)
{
    strcpy(title, p);
    count = 0;
    cout << title << endl;
    cout << count << endl;
    cout << "----" << endl;
}

bool schedule::addtoSchedule(const appointment & myAppt)
{
    cout << appointmentArray[0].getDay();
    return false;
}

appointment.h(我没有写这个,这是提供的) - 对这个问题不是非常重要

#ifndef APPOINTMENT_H
#define APPOINTMENT_H

    #include <fstream>
    #include <cstring>

    using std::ostream;

    //  The Designer decides upon the following data and actions (i.e. Functions)
    //  and places the class in the file appointment.h

    class appointment
    {
        public:

            appointment(void);                                              // default constructor
            appointment(long, const char [],int d, int m, int y);           // 5 argument constructor
            appointment(const appointment &);                               // copy constructor

            void keyBoardInput(void);                                       // Assume no blanks in the desc

            long getSource(void) const;                                     // return source
            void setSource(long);                                           // change source

            void setMonth(int);
            void setDay(int);
            void setYear(int);

            int getMonth(void) const;
            int getDay(void) const;
            int getYear(void) const;

            const char *getDescription(void) const;                         // return the address of the description
            void changeDescription(const char *) ;                          // change an existing description

            void copyTo(appointment &) const;                               // copy invoking instance to parameter

            void incrementDate (void);                                      // advance the date by ONE day
                                                                            // You can assume 30 days in each month

            void printS(ostream &, int dateFormat) const;   // print all fields
            // dateFormat == 1   month/day/year
            // dateFormat == 2   day/month/year

            ~appointment();               // destructor - indicate the address
                                          //    of the variable that is leaving

            private:

            void setDescription(const char *);  //  used to allocated memory

            // data
            long source;          // id of the person scheduling the appointment
            char * desc;          // description of the appointment - Dynamic Data

            int  day;             // day, month, and year when the appointment
            int  month;           // will happen
            int  year;
    };

#endif

appointment.cpp(我没有写这个,这是提供的) - 对这个问题不是非常重要

#include "appointment.h"

#include <iostream>

using std::cin;
using std::cout;

appointment::appointment()
{
    day = 0;
    cout << "default appt\n";
}

appointment::appointment(long lSource, const char cDescription[], int d, int m, int y)
{
    source = lSource;
    day = d;
    month = m;
    year = y;
    setDescription(cDescription);
}
appointment::appointment(const appointment & aToCopy)
{
    source = aToCopy.getSource();
    day = aToCopy.getDay();
    month = aToCopy.getMonth();
    year = aToCopy.getYear();
    setDescription(aToCopy.getDescription());
}


void appointment::setDescription(const char * cSource)
{
    if (desc != NULL) free (desc);

    if (cSource == NULL)
        return;

    desc = (char *)malloc (strlen (cSource) + 1);
    strcpy(desc, cSource);
}

long appointment::getSource(void) const
{
     return source;
}

void appointment::setSource(long lSource)
{
     source = lSource;
}

void appointment::setMonth(int iMonth)
{
     month = iMonth;
}

void appointment::setDay(int iDay)
{
     day = iDay;
}

void appointment::setYear(int iYear)
{
     year = iYear;
}

int  appointment::getMonth(void) const
{
     return month;
}

int  appointment::getDay(void)   const
{
     return day;
}

int  appointment::getYear(void)  const
{
     return year;
}

//return the address of the description
const char * appointment::getDescription(void) const
{
     return desc;
}

//change an existing description
void appointment::changeDescription(const char * cDescription)
{
    setDescription(cDescription);
}

void appointment::copyTo(appointment &p) const
{
    p.source = source;
    p.day = day;
    p.month = month;
    p.year = year;
    p.setDescription(desc);
}

void appointment::incrementDate(void)
{
    int days;

    switch (month)
    {
        case 1: // Jan: 31 Days
        case 3: // Mar: 31 Days
        case 5: // May: 31 Days
        case 7: // Jul: 31 Days
        case 10: // Oct: 31 Days
        case 12: // Dec: 31 Days
            days = 31;
            break;

        case 4: // Apr: 30
        case 6: // Jun: 30
        case 8: // Aug: 30
        case 9: // Sep: 30
        case 11: // Nov: 30
            days = 30;
            break;

        case 2: // Feb: 28/29 Days (Depends on year modulus 4 a modulus 100).
            days = !(year % 4) || !(year % 100) ? 29 : 28;
            break;
    }

    day++;

    if (day > days)
    {
        month++;
        day = 1;

        if (month > 12)
        {
            month = 1;
            year++;
        }
    }
}

void appointment::printS(ostream &out, int dateFormat) const
{
    if (dateFormat == 1)
    {
        out << month << "/" << day << "/" << year << "\n";
    }
    else if (dateFormat == 2)
    {
        out << day << "/" << month << "/" << year << "\n";
    }
    else
        out << "Unsupported dateFormat parameter specified (should be 1 or 2).";
}

appointment::~appointment()
{
    if (desc != NULL)
    {
        free (desc);
        desc = NULL;
    }
}

void appointment::keyBoardInput()
{
    char temp[1024];

    cout << "Please type the description: ";
    cin.getline (temp, sizeof(temp) - 1, '\n');
    cout << std::endl;

    setDescription(temp);
}

主驱动程序调用mySch2.addtoSchedule(myAppt)时发生错误;

如果我取消注释schedule scheduleArray [0] .getDay()中的行,那么一切都运行正常,没有分段错误。一旦该行被取消注释,它就会在运行时抛出错误(在崩溃之后我进入调试器并逐步执行该程序)。

1 个答案:

答案 0 :(得分:0)

在调用desc之前,您永远不会为类nullptr初始化appointmentsetDescription。这在两个构造函数中都会发生。学习使用初始化列表:

appointment::appointment()
    : source(), desc(), day(), month(), year()
{
    cout << "default appt\n";
}

appointment::appointment(long lSource, const char cDescription[], int d, int m, int y)
    : source(lSource), desc(), day(d), month(m), year(y)
{
    setDescription(cDescription);
}

appointment::appointment(const appointment & aToCopy)
    : source(aToCopy.getSource())
    , desc()
    , day(aToCopy.getDay())
    , month(aToCopy.getMonth())
    , year(aToCopy.getYear())
{
    setDescription(aToCopy.getDescription());
}

为什么会出错?

如果没有初始化,desc中的值是不确定的,因此未定义的行为要取消引用,当然也要传递给free

void appointment::setDescription(const char * cSource)
{
    if (desc != NULL) free (desc); // desc contains non-null garbage.

    if (cSource == NULL)
        return;

    desc = (char *)malloc (strlen (cSource) + 1);
    strcpy(desc, cSource);
}

那就是说,我强烈建议改用std::string。它会使这个类的copy-consructor完全消失,并且默认的构造函数是微不足道的。

关于在保留的C ++程序中使用malloc()的评论,因为这个观点已经全部 - 但已经在这个论坛上被击败(我赞同te流行观点)。