Получение предупреждения fgets при попытке запустить оптимизированный файл c

#c #warnings #fgets #strtol

Вопрос:

Это часть гораздо большего файла, но это единственная функция, о которой идет речь. Вот в чем проблема, если я скомпилирую его в gcc неоптимизированным, я получу все, что хочу, без проблем. Однако, если я попытаюсь скомпилировать его как gcc-c-pg -02 main.c, я получу следующее сообщение об ошибке

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

1. Это дает вам хороший совет: проверьте возвращаемое значение fgets перед использованием line в случае, если функция имеет ошибку.

2. Таким же образом вы проверили бы возвращаемое значение любой функции. Прочитайте страницу руководства, чтобы узнать, какое значение оно возвращает при ошибке, а затем проверьте его с if помощью условия: if (fgets(line,MAX_LINE ,stdin) == NULL) { /* do error handling */ }

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

4. Не вижу чего? Мне трудно поверить, что компилятор все еще выдает это предупреждение после добавления проверки ошибок для использования возвращаемого значения fgets. Опубликуйте точный обновленный код и точное предупреждение из этого кода, если вы утверждаете, что это все еще происходит.

5. Вы также должны добавить проверку ошибок в функции преобразования, такие как strtol() . Что, если вы прочитаете что-то, что не является целым числом? Или есть другие вещи после некоторых начальных цифр?

Ответ №1:

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

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

Если fgets произойдет сбой, у вашей программы нет очевидного способа восстановления, поэтому самый простой подход-просто закрыть ее и отобразить сообщение об ошибке. perror Функция-удобный способ сделать это; она выводит удобочитаемое сообщение, соответствующее коду ошибки, из errno переменной, которую fgets следует установить.

Таким образом, элементарной формой проверки ошибок здесь было бы заменить вашу fgets строку на:

 if (fgets(line,MAX_LINE ,stdin) == NULL) {
    perror("Failed to read input");
    exit(1);
}
 

Некоторые вещи, которые вы могли бы улучшить позже:

  • Одной из возможных причин fgets возврата NULL является конец файла: если вообще не было ввода: пользователь нажал клавишу конца файла на своем терминале (обычно Ctrl-D в Unix, Ctrl-Z в Windows) или перенаправил ввод из пустого файла. Это не совсем ошибка, и она не приведет к коду ошибки errno , поэтому perror в этом случае может появиться вводящее в заблуждение сообщение. Попробуйте исправить эту ошибку. Вы могли бы различить два случая, используя ferror функцию.
  • Если строка была успешно прочитана, но не может быть проанализирована как число, strtol произойдет сбой. В настоящее время вы тоже не проверяете это. Посмотрите, как это указывает на этот сбой, и обработайте его соответствующим образом.

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

1. @buckywucky: strtol сигнализирует о сбое не по возвращаемому значению, а скорее по второму endptr аргументу. Так что вам придется посмотреть, как это работает. Вам решать, что делать, если это не удастся. Это может произойти, если пользователь введет что-то, что не является номером, что, строго говоря, не является ошибкой, а просто неправильным использованием. perror и exit , возможно, это не лучший способ справиться с этим; возможно, вам захочется распечатать более индивидуальное сообщение и/или позволить пользователю повторить попытку.