0

I have a base class called Student and three derived classes of MathStudent, EnglishStudent, and HistoryStudent. I am making a new class called StudentList which is supposed to make a dynamic array of pointers to Student such as

    Student** List = new Student*[CurrentSize];

the whole point of the code is to read a text file containing students information and to order them into the list and then access the list to then print out the students information and/or export it into a new file. The problem I am having is with the following block of code:

    CurrentSize += numStudents;

    for(int i = 0; i < CurrentSize; i++)
    {
     File.getline(LastName, 20, ',');
     File.getline(FirstName, 20);
     File.getline(Subject, 8, ' ');

     if(Subject == "Math")
            {
            File>>q1>>q2>>q3>>q4>>q5>>test1>>test2>>final;
            MathStudent M(LastName, FirstName, Subject, q1, q2, q3, q4, q5$
            Mptr = &M;
            List[j] = Mptr;
            }
     else if(Subject == "English")
            {
            File>>attendance>>project>>midterm>>final;
            EnglishStudent E(LastName, FirstName, Subject, attendance, pro$

            List[j] = &E;
            }
     else if(Subject == "History")
            {
            File>>paper>>midterm>>final;
            HistoryStudent H(LastName, FirstName, Subject, paper, midterm,$

            List[j] = &H;
            }
     j++;
    }

Having attempted to debug the code on GDB i found that the segmentation fault is occuring whenever I attempt to pass something into List such as when I say

    List[j] = Mptr;

or

    List[j] = &M;

But I dont understand why or how this results in a segmentation fault. Please any help is very much appreciated.

Bajron Z.
  • 11
  • 2
  • 4
    You need to understand _object lifetimes_. You are storing pointers to objects that are immediately destroyed. [Your pointers are "dangling"](https://stackoverflow.com/questions/17997228/what-is-a-dangling-pointer) after that. – Drew Dormann Jul 20 '21 at 16:53
  • Danger: `for(int i = 0; i < CurrentSize; i++)` when it follows `CurrentSize += numStudents;` will read the tor the total number of students not just the new students in the file. Ods are good this will shoot off the end of a second and subsequent files and since `File>>q1>>q2>>q3>>q4>>q5>>test1>>test2>>final;` doesn't check for a successful read, you'll probably miss the problem entirely. – user4581301 Jul 20 '21 at 17:02
  • 1
    You need something like `List[j] = new MathStudent(LastName, FirstName, Subject, q1, q2, q3, q4, q5);` but using raw pointers comes with some responsibility. You will need to `delete` them when you're done with them to avoid memory leaks, and when you have them in a class or struct you need to either make those objects uncopyable or understand the rule of 3/5 to make copying safe. https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three Leaning how pointers work is important but learn about smart pointers too and prefer using them. – Retired Ninja Jul 20 '21 at 17:02
  • @Bajron, you loop var is `i`, but your index is `j`. Seems like that's the bug. In case it's not - what's the value of `j`? (and of course dangling pointer, use Retired Ninja's advise) – Alexander Malakhov Jul 20 '21 at 17:07
  • @AlexanderMalakhov j is just some other place variable i am using to keep track of the index in List so that if the user wants to add another file with more students it just adds to the list rather than rewriting over it. – Bajron Z. Jul 20 '21 at 17:34
  • 2
    The best thing to do is provide a small-but-complete example program. Use [mre] for inspiration. The real goal of the MRE is it's a powerful debugging technique. It's hard to make a good one without finding and fixing the bug, so if you make one early in the question process, odds are good you can stop writing the question. – user4581301 Jul 20 '21 at 17:36
  • @BajronZ. *But I dont understand why or how this results in a segmentation fault* -- Create a destructor for the `MathStudent` class. Then inside that destructor, put something like `std::cout << "MathStudent destroyed\n";`. Now in that `for` loop, you will see that if the student is `MathStudent` , the destructor is called after this line: `List[j] = Mptr;`. That means that the pointer you are using `&M` is now pointing to something that has just gone up in smoke. That's a visual illustration for you of why the code does not work correctly. – PaulMcKenzie Jul 20 '21 at 17:42
  • @user4581301 thanks for catching that issue with the for loop, but how do i check for a successful read? when I used GDB it showed that the read was successful and all information was being passed properly. – Bajron Z. Jul 20 '21 at 17:44
  • @RetiredNinja I tried writing the assignment as you suggested but i still get a segmentation fault in the same spot. Although I am wondering about how i actually go about making the objects uncopyable. Would i need to make all derived objects uncopyable or simply the base class? – Bajron Z. Jul 20 '21 at 17:54
  • @BajronZ. *Although I am wondering about how i actually go about making the objects uncopyable* -- You are slowly but surely going into [XY Problem](https://xyproblem.info/) territory. What makes you think that there is any issue with copying objects? Also, please post the actual classes -- if the base class does not have a virtual destructor, attempting to issue a `delete` call will result in undefined behavior. – PaulMcKenzie Jul 20 '21 at 18:05
  • Every stream operation returns a reference to the stream. Every stream has a conversion operator that will turn the stream into a boolean that reports whether the stream has failed or not, so you can write code like `if (file >> value) ( use value } else { handle error }` In your case I'd use a combination of [Option 2 in this answer](https://stackoverflow.com/a/7868998/4581301) and what you have. You read lines from the file into a string, pop the string into a `stringstream` and then pull the line apart similar to what you are doing now, but with extra testing. – user4581301 Jul 20 '21 at 18:17
  • 1
    Side note: If not disallowed by the assignment restrictions, consider using [`std::vector`](https://en.cppreference.com/w/cpp/container/vector) instead of your own dynamic array and [`std:: unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) instead of `new` and `delete` when allocating students. – user4581301 Jul 20 '21 at 18:21

0 Answers0