Search code examples
cfgetsdynamic-memory-allocationrealloc

C: Weird behavior after calling realloc() when using fgets() to store strings in a dynamic buffer


The following code loads in a text file called gasses.txt that has 16 terms, each on its own line, and stores these terms one at a time in the buffer search_terms.

#define MAX_LINE_LEN 40
FILE *dict_fp;
int term_len;
int j;

size_t number_search_terms = 10;
int i;
char **search_terms = malloc(sizeof(char *) * number_search_terms);
for (i=0; i < number_search_terms; i++)
    search_terms[i] = malloc(MAX_LINE_LEN);

dict_fp = fopen("gasses.txt", "r");
for (i=0; fgets(search_terms[i], MAX_LINE_LEN, dict_fp) != NULL; i++){

    // get rid of the newline.
    term_len = strlen(search_terms[i]);
    search_terms[i][term_len-1] = 0;

    // resize buffer when it gets full
    if (i == number_search_terms-1){
        number_search_terms *= 2;
        search_terms = realloc(search_terms, number_search_terms);      
        for (j = number_search_terms/2; j < number_search_terms; j++)
            search_terms[j] = malloc(MAX_LINE_LEN);
    }

    printf("%s\n", search_terms[i]);

    printf("%s\n\n", search_terms[0]);

}

The output looks like this. After the first memory reallocation, the string stored in search_terms[0] gets corrupted.

nitrogen
nitrogen

oxygen
nitrogen

argon
nitrogen

carbon dioxide
nitrogen

neon
nitrogen

helium
nitrogen

methane
nitrogen

krypton
nitrogen

hydogen
nitrogen

nitrous oxide
���

xenon
���

ozone
���

nitrogen dioxide
���

iodine
���

ammonia
���

water vapour
���

This is gasses.txt:

oxygen
argon
carbon dioxide
neon
helium
methane
krypton
hydogen
nitrous oxide
xenon
ozone
nitrogen dioxide
iodine
ammonia
water vapour

Solution

  • When you first malloc for search_terms, you correctly use sizeof(char *) * number_search_terms for the size.

    However, when you realloc, you use number_search_terms instead. This new size is 1/4 or 1/8 the correct size (depending on your pointer size) and so you end up writing past the end of this buffer.