Search code examples
arrayscmallocrealloc

What am I doing wrong with malloc and realloc of array of struct?


I'm trying to build in C an array of structures without defining the length of the maximum size of the array.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct text {
   char *final;
} text;

int main() {
    int n, sizearray = 10, i;
    char *str;
    text *testo;
    testo = (text *)malloc(sizeof(text) * sizearray);

    fgets(str, 1024, stdin);
    i = 0;
    while (str[0] != 'q') {
        if (i == sizearray - 1) {
            testo = (text *)realloc(testo, sizearray * 2 * sizeof(text));
        }
        n = strlen(str);
        n = n + 1;
        testo[i].finale = (char *)malloc(sizeof(char) * n);
        strcpy(testo[i].finale, str);
        i++;
        fgets(str, 1024, stdin);
    }

    for (i = 0; i < sizearray; i++)
        printf("%s \n", testo[i].finale);

    return 0;
}

this gives me

process finished with exit code 139 (interrupted by signal 11:SIGSEV).

What am I doing wrong?


Solution

  • There are multiple issues in your code:

    • [major] str is an uninitialized pointer. You should make it an array of char defined with char str[1024].
    • [major] you do not adjust sizearray when you double the size of the array, hence you will never reallocate the array after the initial attempt at i = 9.
    • [major] the final loop goes to sizearray but there are potentially many uninitialized entries at the end of the array. You should stop at the last entry stored into the array.
    • you should also check the return value of fgets() to avoid an infinite loop upon premature end of file.
    • you should test for potential memory allocation failures to avoid undefined behavior.

    Here is a modified version:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    typedef struct text {
       char *finale;
    } text;
    
    int main() {
        char str[1024];
        text *testo = NULL;
        size_t sizearray = 0;
        size_t i, n = 0;
    
        while (fgets(str, sizeof str, stdin) && *str != 'q') {
            if (n == sizearray) {
                /* increase the size of the array by the golden ratio */
                sizearray += sizearray / 2 + sizearray / 8 + 10;
                testo = realloc(testo, sizearray * sizeof(text));
                if (testo == NULL) {
                    fprintf(stderr, "out of memory\n");
                    return 1;
                }
            }
            testo[n].finale = strdup(str);
            if (testo[n].finale == NULL) {
                fprintf(stderr, "out of memory\n");
                return 1;
            }
            n++;
        }
    
        for (i = 0; i < n; i++) {
            printf("%s", testo[i].finale);
        }
        for (i = 0; i < n; i++) {
            free(testo[i].finale);
        }
        free(testo);
        return 0;
    }