简体   繁体   中英

Segmentation fault in class definitions cannot figure out where

I am having a segmentation error that I have been trying to find for the past 4 hours. Here is the code and some information that might be of use from valgrind.

  Course::Course()
{
    courseid = "None";
    courseName = "None";
    enrolled[2] = {0};

}

Course::Course(string courseNum, string coursename, string filename)
{
    courseid = courseNum;
    courseName = coursename;
    enrolled[2] = {0};
    readStudentData(filename);
    sortRow(0);
    sortRow(1);
    sortRow(2);

}


void Course::readStudentData(string filename)
{
    std::ifstream inFile; //declare file input stream object
    string first, last, zid;
    int section;

    inFile.open(filename.c_str()); //open file 
    if (!inFile)
    {
        cout << "File did not open successfully!"; //error checking
        exit(EXIT_FAILURE);
    }

    inFile >> first; //read first
    while (inFile)
    {
        inFile >> last;
        inFile >> zid;
        inFile >> section;
        section--; //match section with array subscript

        Student newStudent(last, first, zid);   //fill  contents read to new student object



        Students[section][enrolled[section]] = newStudent; //fill Students array with new student 

        enrolled[section]++; //add the student to the enrolled counter

        inFile >> first;
    }

    inFile.close();
}


void Course::sortRow(int RowtoSort)
{
    int i, j;
    Student bucket;

    for(i = 1; i < enrolled[RowtoSort];i++)
    {
        bucket = Students[RowtoSort][i]; //assign bucket with temp value for swap


            for(j = i; (j > 0) && (Students[RowtoSort][j-1].getLastName().compare(bucket.getLastName())) < 0; j--)
        {
            Students[RowtoSort][j] = Students[RowtoSort][j-1]; //assign j to element j-1 so now both j and j-1 are the same in the array
        }
        Students[RowtoSort][j] = bucket; //now j-1 value is at j and since j-- assign it to bucket to place the proper value at j-1  

    } // end outer loop

}


void Course::print()
{
    cout << courseid << " " << courseName << endl; //header

    cout << "Section 1" << endl; //print section 1
    cout << left << "Name" << setw(40) << "Z-id" << endl;

    for(int i=0;i<enrolled[0];i++)
    {
        Students[0][i].print();          
    }

    cout << "Section 2" << endl;    //print section 2
    cout << left << "Name" << setw(40) << "Z-id" << endl;
    for(int i=0;i<enrolled[0];i++)
    {
        Students[1][i].print();   
    }

    cout << "Section 3" << endl;    //print section 3
    cout << left << "Name" << setw(40) << "Z-id" << endl;
    for(int i=0;i<enrolled[0];i++)
    {
        Students[2][i].print();   
    }


}

Here is the information valgrind gave when

==4223== Use of uninitialised value of size 8
==4223==    at 0x4EF15F1: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==4223==    by 0x4023E6: Student::operator=(Student const&) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401B9F: Course::readStudentData(std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401836: Course::Course(std::string, std::string, std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x4012F9: main (assign3.cpp:27)
==4223== 
==4223== Use of uninitialised value of size 8
==4223==    at 0x4EF15F1: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==4223==    by 0x402401: Student::operator=(Student const&) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401B9F: Course::readStudentData(std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401836: Course::Course(std::string, std::string, std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x4012F9: main (assign3.cpp:27)
==4223== 
==4223== Use of uninitialised value of size 8
==4223==    at 0x4EF15F1: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==4223==    by 0x40241C: Student::operator=(Student const&) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401B9F: Course::readStudentData(std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401836: Course::Course(std::string, std::string, std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x4012F9: main (assign3.cpp:27)
==4223== 
==4223== Invalid read of size 8
==4223==    at 0x4EF15F1: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==4223==    by 0x4023E6: Student::operator=(Student const&) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401B9F: Course::readStudentData(std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401836: Course::Course(std::string, std::string, std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x4012F9: main (assign3.cpp:27)
==4223==  Address 0x8050190f0 is not stack'd, malloc'd or (recently) free'd
==4223== 
==4223== 
==4223== Process terminating with default action of signal 11 (SIGSEGV)
==4223==  Access not within mapped region at address 0x8050190F0
==4223==    at 0x4EF15F1: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==4223==    by 0x4023E6: Student::operator=(Student const&) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401B9F: Course::readStudentData(std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x401836: Course::Course(std::string, std::string, std::string) (in /home/ruslan/241Assign3/assign3)
==4223==    by 0x4012F9: main (assign3.cpp:27)

I have another student class which has been complied and been tested to work correctly so the error must be in the course.

Course Header file:

#ifndef COURSE_H
#define COURSE_H

#include "student.h"

using std::string;

    class Course
    {
        private:
        string courseid;
        string courseName;
        Student Students[3][45];
        int enrolled[2];

        public:
        Course(); //default constructor
        Course(string, string, string); //alternate constructor 
        void readStudentData(string);
        void sortRow(int);
        void print();           

    };

#endif //COURSE.H

Student class definitions:

Student::Student()
{
    firstName = "None";
    lastName = "None";
    zid = "None";
}


Student::Student(string assignFirst, string assignLast, string assignZID)
{
    firstName = assignFirst;
    lastName = assignLast;
    zid = assignZID;
}



string Student::getLastName()
{
    return lastName;
}


void Student::print()
{
    cout << lastName << ", " << firstName << std::setw(15) << zid << endl; 
}

You have undefined behavior in a couple of places. The first is in the Course constructors, where you write to enrolled out of bounds . The second is when use use an uninitialized value from that array as an index to another array.

If you want to initialize the whole array in the constructor, either initialize each index one by one, or use an initializer list to initialize the whole array to the same value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM