Search code examples
cpointersmallocrealloc

C: Realloc behaves in a way i cant figure out why


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

int main(int argc, char* argv[]){

    char buffer[103];
    char **words = malloc(1 * sizeof(*words));
    size_t counter = 0;
    size_t array_size = 2;


    for(int i = 0; i < 5; i++){
        if(!fgets(buffer, 103, stdin)){
            fputs("fgets failed", stderr);
        }
        words[counter] = buffer;
        char **more_words = realloc(words, array_size * sizeof(*more_words));
        words = more_words;
        array_size++;
        counter ++;
    }
    printf("********************************************************");


    for(int i = 0; i < 5; i++){
        printf("%s\n", words[i]);
    }


}

Now this is the simplified code im working on. I know i dont handle lots of errors that can occour.

The point is, that when you execute this, the word array seems to have 5 entries of the 'last' entry.

Say you give fgets :

1
2
3
4
5

, then

words[0] = 5;
words[1] = 5;
words[2] = 5;
words[3] = 5;
words[4] = 5;

Why is not:

words[0] = 1;
words[1] = 2;
words[2] = 3;
words[3] = 4;
words[4] = 5;

?


Solution

  • if(!fgets(buffer, 103, stdin)){
            fputs("fgets failed", stderr);
    }
    words[counter] = buffer;
    

    You have one buffer that are overwritten each time when calling fgets, so that all strings in words effectively point to the same char array. Try this:

    if(!fgets(buffer, 103, stdin)){
            fputs("fgets failed", stderr);
    }
    // here make a new buffer and copy the string just read into it.
    char *new_buffer = malloc(strlen(buffer) + 1);
    strcpy(new_buffer, buffer);
    words[counter] = new_buffer;