2013-10-19 3 views
1

두 클래스 (약속, 일정)와 드라이버 (주)가 있습니다.액세스 위반 (세그먼트 화 오류)

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 (I이 제공되었으며,이 작성하지 않은) - 이 질문에 아주 중요하지 않다.

#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 (나는이 작성하지 않은,이 제공되었다) -이 질문의 주요 드라이버가 mySch2.addtoSchedule이 (myAppt) 호출 할 때 내 오류가 발생

#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); 
} 

슈퍼 중요하지 않다;

일정의 내부에서 주석 처리를 제거하면 약속의 배열 [0] .getDay()가 실행되고 세그먼트 화 오류없이 모두 올바르게 작동합니다. 해당 라인의 주석 처리가 해제되자 마자 실행 중 오류가 발생합니다 (충돌 후 디버거로 들어가서 프로그램을 단계별로 실행).

+0

프로그램의 일부 다른 부분이 메모리를 손상시켜야합니다. 분할 위반은 포인터 오용으로 인해 발생하며 코드의 해당 부분에서 포인터를 사용하지 않습니다. valgrind를 사용하여 메모리 문제를 잡으려고 시도 했습니까? – Barmar

+0

그건 전체 코드입니다. (나는 valgrind가 무엇인지 확실하지 않습니다. –

+0

Valgrind는 메모리 관리 문제를 디버깅하는 도구로 정확히 무엇을 가지고 있는지 알고 싶습니다. – Barmar

답변

0

setDescription을 호출하기 전에 appointment에 대해 desc에서 nullptr까지 절대로 초기화하지 마십시오. 이것은 두 생성자 모두에서 발생합니다.

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을 사용하는 것이 좋습니다. 이 클래스의 복사 생성자를 완전히 사라지게하고 기본 생성자를 사소하게 만듭니다.

C++ 프로그램에서 malloc()을 사용하는 것에 대한 의견은 저 의견이 이미이 포럼에서 이미 끝났기 때문에 (그리고 나는 일반적인 의견에 동의 함).

+0

Ahhh, 약속 클래스가 제공 되었기 때문에 실제로 너무 강하게 보지 않을 것 같았습니다. null로 설정하는 것은 실제로 내 마음을 넘어서는 일이 아니 었습니다. 모든 도움과 설명에 감사드립니다. 당신이 그것을 언급 한 이후로 std :: string을 더 검사 할 것입니다. 아직 많은 경험을하지 못했습니다. (나는 C++에서 여전히 새로운 것으로, 인상 벡터 아래에 있었습니까? 둘 다 보일거야!). 내가 제공 한 코드에서 얼마나 벗어날 수 있었는지 다시 고칠 수 있지만 null로 설정하면 문제가 해결되어 매우 행복합니다^_^다시 –