0

I have spent the past few hours trying to figure out why I am getting a seg-fault. My code runs fine, being that my nameList pointer array is initialized with the names that I enter. However, when I pass nameList to my function to dynamically allocate the right amount of space per name in the createStudentList function. If you have any ideas, please inform me with an explanation, I am not looking only for an answer to fix it. Thank you. (This is an assignment, so some guidelines need to be followed [such as using char arrays instead of strings].)

Here is my code:

#include "main.h"
using namespace std;

const int MAXCHAR = 101;

struct Student
{
    char *name;
    double gpa;
};

Student ** createStudentList(char ** names, int size);

int main()
{
    int size = 0;
    char temp[MAXCHAR];
    char **nameList = nullptr;
    Student **studentList = nullptr;

    cout << "Enter amount of names: ";
    cin >> size;
    cout << endl;
    cin.clear();
    cin.ignore(10, '\n');
    nameList = new char *[size];

    for(auto i = 0; i < size; i++)
    {   
        cout << "Enter name: ";
        cin.get(temp, MAXCHAR, '\n');
        cout << endl;
        cin.ignore(10, '\n');
        nameList[i] = new char[strlen(temp) + 1]; 
        strcpy(nameList[i], temp);
    }   

    studentList = createStudentList(nameList, size);

    return 0;
}

Student ** createStudentList(char ** names, int size)
{
    Student **tempStudentList = nullptr;
    tempStudentList = new Student *[size];


    for(auto idx = 0; idx < size; idx++)
    {
        tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];
        strcpy(tempStudentList[idx]->name, names[idx]);
        tempStudentList[idx]->gpa = 0;
    }
    return tempStudentList;
}
10
  • 3
    This is not modern C++, use vector and strings from standard library. You should not rely on raw pointers. Commented May 20, 2016 at 7:04
  • Please show us a case that it cause a seg fault Commented May 20, 2016 at 7:05
  • @tomekpe I would, but I have to follow the guidelines of the assignment. I am taking a C++ class and it is required to do it this way. Sorry Commented May 20, 2016 at 7:05
  • @tomekpe: it is 100% true. However, it is an assignment and the OP has specific restriction Commented May 20, 2016 at 7:06
  • @HumamHelfawi Not sure what you mean, but this is what gdb tells me. I typed two names (Ryan and Ben) and then try to pass nameList to the function. Program received signal SIGSEGV, Segmentation fault. 0x0000000000400e2c in createStudentList (names=0x614c20, size=2) at main.cpp:52 52 tempStudentList[idx]->name = new char[strlen(names[idx]) + 1]; Commented May 20, 2016 at 7:09

2 Answers 2

2

You're not allocating the Student instances in the loop. Try this:

for(auto idx = 0; idx < size; idx++)
{
    tempStudentList[idx] = new Student;

    tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];
    strcpy(tempStudentList[idx]->name, names[idx]);
    tempStudentList[idx]->gpa = 0;
}

Also, as pointed out in the comments, this isn't modern C++. You'd be better off using std::string and std::vector. For example, change Student to be:

struct Student
{
    std::string name;
    double gpa;
};

add use std::vector in createStudentList:

std::vector<Student> createStudentList(const std::vector<string> &names)
{
    std::vector<Student> students;    

    for(auto idx = 0; idx < names.size(); idx++)
    {
        Student student;
        student.name = names[index];
        student.gpa = 0

        students.push_back(student);
    }

    return students;
}

This will save you having to allocate raw memory which you would otherwise need to delete.

Sign up to request clarification or add additional context in comments.

3 Comments

I would reserve before pushing back. students.reserve(names.size());
std::vector<Student> students(names.size()); would work as well.
Thank you @Sean! I will give that a try, can't believe I hadn't noticed that. Sometimes you stare for so long you miss the obvious. Thank you for the tips on vector. I am in school right now and am rather disappointed that my teacher is teaching us C++ that is not modern any longer. I will really need to learn more once this semester is over. Thank you for the help though! Also, that is good to know that those will help with the deletion too. After this function is complete my other objective is to delete the allocated memory.
2

The reason of segmentation fault:

for(auto idx = 0; idx < size; idx++)
{
    // tempStudentList[idx] is `Student *` and you don't allocate memory for it
    // this is UB
    tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];
    strcpy(tempStudentList[idx]->name, names[idx]);
    tempStudentList[idx]->gpa = 0;
}

But, tempStudentList don't need to be Student** at all, Student* should be sufficient.

Student * createStudentList(char ** names, int size)
{
    Student *tempStudentList = new Student[size];
    for(auto idx = 0; idx < size; idx++)
    {
        tempStudentList[idx].name = new char[strlen(names[idx]) + 1];
        strcpy(tempStudentList[idx].name, names[idx]);
        tempStudentList[idx].gpa = 0;
    }
    return tempStudentList;
}

BTW: You need to delete many things, nameList, nameList 's elements, studentList, name of Student, and so on. That's why we should use STLs.

1 Comment

Thank you for the help @songyuanyao. It now works! As for the unnecessary **, I didn't have any other choice with the parameters I was given for this assignment. As for the delete, I will be taking care of all of that in the next function I make which is a delete function. Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.