Gus
Gus

Reputation: 198

Using realloc on array of structures

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

Upvotes: 0

Views: 1179

Answers (2)

pmg
pmg

Reputation: 108968

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 */;
}

Upvotes: 0

interjay
interjay

Reputation: 110069

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.

Upvotes: 3

Related Questions