Чтение страниц руководства и некоторого кода на самом деле не помогло мне понять разницу между - или, что лучше, когда мне следует использовать - perror("...")
или fprintf(stderr, "...")
.
Вызов perror
даст вам интерпретируемое значение errno
, которое является значением локальной ошибки потока, записанным системными вызовами POSIX (т. Е. Каждый поток имеет собственное значение для errno
). Например, если вы позвонили open()
, и возникла ошибка (т. Е. Она вернулась -1
), вы можете позвонить perror
сразу же после этого, чтобы узнать, в чем была ошибка. Имейте в виду, что если вы тем временем вызовете другие системные вызовы, то значение в errno
будет записано, и вызов perror
не будет иметь никакого смысла при диагностике вашей проблемы, если ошибка была сгенерирована более ранним системным вызовом.
fprintf(stderr, ...)
с другой стороны, можно использовать для печати ваших собственных сообщений об ошибках. Печатая в stderr
, вы избегаете смешивания вывода отчета об ошибке с «нормальным» выводом, который должен быть stdout
.
Имейте в виду, что fprintf(stderr, "%s\n", strerror(errno))
это похоже на то, что perror(NULL)
при вызове strerror(errno)
будет сгенерировано напечатанное строковое значение для errno
, и вы можете объединить это с любым другим настраиваемым сообщением об ошибке через fprintf
.
If you use a function that effects errno then it makes sense to use perror
.Если вы используете функцию, которая не влияет на errno и просто возвращает код ошибки, вам следует использовать fprintf (stderr, fmt, ...). Например, strtol вернет LONG_MAX или LONG_MIN, если строка выходит за пределы допустимого диапазона, и установит для errno значение ERANGE. Поэтому, если strtol выходит из строя из-за выхода за пределы диапазона, я бы использовал perror.strerror
не обязательно быть поточно-ориентированной. Это глупо, но это стандарт.strerror_l
может использоваться вместо этого в качестве замены в системах POSIX 2008.strerror_r
также доступен в старых системах, но имеет действительно неприятные проблемы с некоторыми системами, имеющими его несовместимые версии.perror
добавляет'\n'
в конце, так что формат будет"%s\n"
, нет?strerror_s
самом деле это не так уж плохо как интерфейс._s
мусора в стандарт было в основном игрой MS («Если вы воспользуетесь нашими интерфейсами, мы рассмотрим, как сделать так, чтобы наши продукты поддерживали ваш стандарт»), и, конечно, теперь они не следуют этому. На самом деле я согласен, что этот интерфейс сам по себе неплох. Что плохо, так это пропаганда (в виде предупреждений компилятора) о том, что большая часть стандартной библиотеки «небезопасна» и что все семейство_s
функций должно использоваться вместо стандартных.Они делают разные вещи.
Вы используете
perror()
для печати сообщения,stderr
которое соответствуетerrno
. Вы можете использоватьfprintf()
для печати ничего кstderr
, или любой другой поток.perror()
это очень специализированная функция печати:эквивалентно
источник
perror(const char *s)
: печатает переданную вами строку, за которой следует строка, описывающая текущее значениеerrno
.stderr
: это выходной поток, используемый для передачи ваших собственных сообщений об ошибках (по умолчанию на терминал).Соответствующий:
char *strerror(int errnum)
: присвойте ему номер ошибки, и он вернет соответствующую строку ошибки.источник
perror () всегда пишет в stderr; strerr (), используемый вместе с fprintf (), может писать в любой вывод, включая stderr, но не исключительно.
Кроме того, perror накладывает свой собственный текст в формате «текст: описание ошибки».
источник
Функция Perror требует больше времени для выполнения, вызов переходит из пользовательского пространства в пространство ядра, тогда как вызовы fprintf отправляются с api на ядро
источник