#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
, возможно, это не лучший способ справиться с этим; возможно, вам захочется распечатать более индивидуальное сообщение и/или позволить пользователю повторить попытку.