Alon
Alon

Reputation: 464

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;

?

Upvotes: 0

Views: 43

Answers (2)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

The problem is not the realloc, but what you assign to pointers that you allocated:

words[counter] = buffer;

The buffer is the same pointer all the time, so you end up with the last string read into the buffer.

You need to malloc and copy the buffer for each line:

words[counter] = malloc(strlen(buffer)+1);
strcpy(words[counter], buffer);

It goes without saying that you should be NULL-checking the value returned by realloc before assigning it back to words.

Upvotes: 4

fluter
fluter

Reputation: 13786

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;

Upvotes: 1

Related Questions