Ошибка Realloc после второго вызова

Я пытаюсь прочитать список слов для сортировки, и я начинаю с довольно небольшого массива (10 элементов), а затем хотел бы увеличить размер массива на 10, если текущей емкости недостаточно. Кажется, это работает с первым realloc, но я получаю SIGABRT при попытке снова вызвать realloc. Я уверен, что это простая вещь, которую я не вижу, но я не могу понять это. Вот моя программа:

int main(int argc, char *argv[]){
    char *string = malloc(100);
    // Array of pointers starting with 100 elements
    char **toSort = malloc(100*sizeof(char *));
    if(toSort == NULL) {
        exit(1);
    }

    for(int i = 0; i < 100; i++) {
        // Each string can be up to 100 characters long
        toSort[i] = malloc(101);
        if(toSort[i] == NULL) {
            exit(1);
        }
    }

    // Get all lines in the file
    int counter = 0;
    int max = 10;
    char *toAdd;


    FILE *txt = fopen("wlist0.txt", "r");


    while(fgets ( string, 100, txt ) && counter < max) {;

        toAdd = malloc(100);
        if(toAdd == NULL) {
            exit(1);
        }
        strcpy(toAdd, string);

        toSort[counter] = string;
        counter++;

         //if the array needs to be enlarged
        if(counter == max) {
            char **new = realloc(toSort, (max+10) * sizeof(char));
            if(new == NULL) {
                exit(1);
            }
            for(int i = max; i < max + 10; i++) {
                toSort[i] = malloc(101);
                if(toSort[i] == NULL) {
                    exit(1);
                }
            }
            toSort = new;
            max += 10;
        }
    };

    for(int i = 0; i < max; i++) {
        char *word = toSort[i];
        printf("%s", word);
    }

    for(int i = 0; i < max; i++) {
       free(toSort[i]);
    }

    free(toSort);


    return 0;
};

Как говорится в моих комментариях, мои строки имеют максимальную длину 100 символов. Я полагаю, что я мог бы также динамически выделять память для строк, но я буду беспокоиться об этом, когда у меня будет работать другой realloc. Любая помощь будет принята с благодарностью.


person user25758    schedule 29.04.2018    source источник
comment
Вы должны использовать функции вместо того, чтобы помещать все в свой main(). Это упростит чтение вашего кода!   -  person Ronan Boiteau    schedule 29.04.2018
comment
@purec Отмечено. Я удалил их.   -  person user25758    schedule 29.04.2018
comment
@ user3121023 Спасибо! Кажется, это помогает. Я подумал, что это что-то маленькое.   -  person user25758    schedule 29.04.2018
comment
Вы абсолютно правы! Я так долго над этим работал, что забыл во всем разобраться.   -  person user25758    schedule 29.04.2018
comment
@purec: Стандарт C требует, чтобы передача NULL в free() была допустимой.   -  person alk    schedule 29.04.2018
comment
@alk: да, я был неправ. Но по крайней мере смысла нет.   -  person purec    schedule 29.04.2018
comment
Да, я преследую их, как только вижу. Лучше каждый раз увеличивать мой массив на единицу? У меня сложилось впечатление, что realloc довольно требователен, но, с другой стороны, отсутствие неиспользуемой памяти также является хорошей идеей.   -  person user25758    schedule 29.04.2018
comment
Кажется, у вас есть некоторые операции с toSort, хотя он имеет тот же старый размер. Просто перейдите к Sort = new; перед циклом.   -  person purec    schedule 29.04.2018
comment
@purec почему? Никому не помешает сделать free(NULL), на самом деле это одно из приятных свойств free, когда вы освобождаете массивы динамически выделяемых указателей.   -  person Pablo    schedule 29.04.2018
comment
@Pablo if(!p) free(p) (наш случай) не имеет смысла.   -  person purec    schedule 29.04.2018
comment
@purec он? Я не понимаю, что вы имеете в виду. Где именно ОП это делает?   -  person Pablo    schedule 29.04.2018
comment
Тогда о чем мы говорим?   -  person purec    schedule 29.04.2018
comment
@purec Я говорю о (теперь удаленном) вашем комментарии, в котором говорилось, что не освобождайте NULL-указатели, на что я ответил, почему бы и нет. alk также ответил на то же самое.   -  person Pablo    schedule 29.04.2018


Ответы (1)


Этот код присваивает значения toSort после того, как память, на которую он указывает, освобождается/модифицируется realloc():

     //if the array needs to be enlarged
    if(counter == max) {
        char **new = realloc(toSort, (max+10) * sizeof(char));
        if(new == NULL) {
            exit(1);
        }
        for(int i = max; i < max + 10; i++) {
            toSort[i] = malloc(101);  <--- toSort is invalid here
            if(toSort[i] == NULL) {
                exit(1);
            }
        }
        toSort = new;
        max += 10;
    }

Это будет работать лучше:

     //if the array needs to be enlarged
    if(counter == max) {
        char **new = realloc(toSort, (max+10) * sizeof( *new )); <-- fixed here, too
        if(new == NULL) {
            exit(1);
        }
        toSort = new;
        for(int i = max; i < max + 10; i++) {
            toSort[i] = malloc(101);
            if(toSort[i] == NULL) {
                exit(1);
            }
        }
        max += 10;
    }

В вашем коде могут быть и другие ошибки. Я не исследовал его полностью.

person Andrew Henle    schedule 29.04.2018
comment
Спасибо за это! Я заметил то же самое, и я как раз был в процессе его изменения. Это работает, и я отмечу это как принятое. - person user25758; 29.04.2018