0

I've been scratching my head for hours on this. This reads data from a text file into the struct (each line has four strings, and each line represents a new student). I am getting a seg fault on the realloc (near the end). I have a suspicion that I am not understanding how the pointer is interacting with malloc/realloc.

struct student* createInitialStudentArray(FILE *fp) {
    char buf[20+1] = {0};
    int word = 1, studcount = 1;
    struct student* studentArray = malloc(sizeof(struct student));
    assert(studentArray != NULL);
    while (fscanf(fp, " %20s", buf) != EOF) {
        if (word % 4 == 1) {
            sscanf(buf, "%4d", &studentArray[studcount].studentID);
            word++;
        }
        else if (word % 4 == 2) {
            strcpy(studentArray[studcount].lastName, buf);
            word++;
        }
        else if (word % 4 == 3) {
            strcpy(studentArray[studcount].firstName, buf);
            word++;
        }
        else if (word % 4 == 0) {
            sscanf(buf, "%10lld", &studentArray[studcount].phoneNumber);
            word = 1;
            studcount++;
            studentArray = realloc(studentArray, studcount * sizeof(struct student));
            assert(studentArray != NULL);
        }
    }

    return studentArray;
}

What is causing this seg fault?

Thanks in advance,

Gus

1
  • 2
    despite not being the root cause of your segfault, the way you're using realloc may lead to memory leaks when realloc can't allocate more memory, because it will return NULL and you'd lose the pointer to the previous buffer Commented Jul 13, 2011 at 14:06

2 Answers 2

3

If your array has studcount elements, then studentArray[studcount] is past the end of the array, and writing there is not allowed. The valid elements to access are 0 to studcount-1. You should replace studentArray[studcount] with studentArray[studcount-1] everywhere to write into the last element.

Note that doing it this way will give you a studcount value that is too large by 1 when the loop is done, because the last element of the array is always empty or incomplete.

As mentioned by pmg in the comments, another solution is to initialize studcount to 0 which will fix both the above issues, but then you need to make sure to allocate room for at least studcount+1 elements before writing a new one.

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

Comments

0

Your loop and scanf structure looks wrong..

First you read a string (the scanf in the while condition), then an int (word == 1), then another string (while condition again, word == 2), another string (while condition again, word == 3), and finally another string and a long long int (word == 4).

I'd rewrite your inner loop with a switch

/* pseudo-code */
while (fgets(buf, sizeof buf, stdin)) {
    /* realloc here */
    chk = sscanf(buf, "%4d%20s%20s%10lld",
                &studentArray[studcount].studentID,
                studentArray[studcount].lastName,
                studentArray[studcount].firstName,
                &studentArray[studcount].phoneNumber);
    if (chk != 4) /* deal with error */;
}

3 Comments

Thanks that looks much cleaner.
One problem: sscanf doesn't remember locations in a string, right? So everytime I call sscanf, it will start at the beginning, so how would I scan the second word in the string?
Hmmm ... yes, you are correct. Better do it all 1 single time. Revising answer :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.