Ошибка при перераспределении при попытке выделить больше памяти

#c #linux #malloc #realloc

#c #linux #malloc #перераспределение

Вопрос:

Я разрабатываю функцию, в которой размер массива начинается с 10, если строка fgets больше, ему нужно выделить больше памяти, но я получаю сообщение об ошибке, когда строка слишком большая, например, если я набираю что-то с 15 символами, все в порядке, но с 30 я получаю ошибку! И я не знаю почему. Итак, я надеюсь, вы можете мне сказать.

-= РЕШАЕМАЯ В ЭТОМ КОДЕ =-

Мой основной:

 char *buf;

shellExecute(amp;buf);
  

Мой код:

  char* shellExecute(char** buf){
    
        int bufSize = 10;
        *buf = malloc(bufSize * sizeof(char));
        if(*buf == NULL){
            printf("[ERROR] can't malloc %d bytesn", bufSize);
            exit(0);
        }
        char *readpos = *buf;
        
        while (1){  
        
        fgets(readpos, bufSize, stdin);
    
        /* Search from the end, as there's where the newline should be */
            if (readpos[strlen(readpos)-1] == 'n'){
                break;
            }   
    
        /* Need to allocate more memory */
             bufSize  = bufSize;
             *buf = realloc(*buf, *buf   strlen(*buf) * sizeof(char));
    
        /* Set the pointer to next position to read into */
            readpos = *buf   strlen(*buf);
        /* Loop takes case of trying again */
        }   
    }
  

Моя ошибка:

введите описание изображения здесь

Комментарии:

1. Используйте отладчик и выполните пошаговый код….

2. Какой смысл передавать char** , если вы return *buf все равно это делаете?

3. @KamilCuk Это не проблема, потому что у меня уже была функция void и все еще с ошибкой

4. Пожалуйста, не редактируйте вопрос и / или ответ с помощью вашего фиксированного кода. Они имеют смысл только тогда, когда речь идет о неправильном коде, и они могут помочь людям, у которых есть аналогичный неправильный код. Если вы хотите сообщить о том, как вы устранили проблему, опубликуйте вместо этого свой собственный ответ.

5. @NateEldredge Хорошо, спасибо

Ответ №1:

Общий размер начинается с 10. Вы делаете

 fgets(readpos, bufSize, stdin);
  

На первой итерации readpos указывает на начало буфера, так что это нормально. Допустим, считывается 9 байт, оставляя место для нулевого терминатора. Теперь вы делаете

 bufSize  = bufSize;
*buf = realloc(*buf, bufSize * sizeof(char));
  

Итак, сейчас bufSize 20 и *buf имеет общий размер 20. Далее вы делаете

 readpos = *buf   strlen(*buf);
  

так что readpos теперь указывает на *buf 9 .

Ваш следующий fgets попытается прочитать 20 байт в буфер общего размера 20, но начиная со смещения 9, после которого доступно только 11 байт. Это может привести к переполнению буфера на 9 байт, вызывая неопределенное поведение.

Вероятно, вы хотите вести отдельный подсчет того, сколько байтов фактически было прочитано, и использовать это для вычисления оставшегося места в буфере, в который вы перейдете fgets .

Другая ошибка заключается в том, что вам нужно проверить возвращаемое значение fgets , чтобы определить, когда файл закончился или произошла ошибка. В нынешнем виде, когда происходит любая из этих вещей, ваша программа будет бесконечно зацикливаться.

Комментарии:

1. Итак, мне нужно переформулировать это readpos = *buf strlen(*buf); помещение readpos = *buf; ?

2. @prt05: это позволит избежать переполнения буфера, но тогда вы будете перезаписывать ранее прочитанные данные новыми данными вместо добавления, что, я думаю, не то, что вы хотите.