C: Realloc ведет себя так, как я не могу понять, почему

#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]);
    }


}

Теперь это упрощенный код, над которым я работаю. Я знаю, что не обрабатываю много ошибок, которые могут произойти.

Дело в том, что когда вы выполняете это, словесный массив, кажется, содержит 5 записей "последней" записи.

Скажем, вы даете fgets:

1
2
3
4
5

, затем

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

Почему нет:

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

?

2 ответа

Решение
if(!fgets(buffer, 103, stdin)){
        fputs("fgets failed", stderr);
}
words[counter] = buffer;

У вас есть один буфер, который перезаписывается каждый раз при вызове fgets, так что все строки в words эффективно указывать на тот же массив символов. Попробуй это:

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;

Проблема не в realloc, но то, что вы назначаете указателям, которые вы выделили:

words[counter] = buffer;

buffer один и тот же указатель все время, так что вы получите последнюю строку, прочитанную в буфер.

Вам нужно malloc и скопируйте буфер для каждой строки:

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

Само собой разумеется, что вы должны быть NULL- проверка значения, возвращаемого realloc прежде чем назначить его обратно words,

Другие вопросы по тегам