Чтение страниц руководства и некоторого кода на самом деле не помогло мне понять разницу между - или, что лучше, когда мне следует использовать - perror("...")
или fprintf(stderr, "...")
.
Чтение страниц руководства и некоторого кода на самом деле не помогло мне понять разницу между - или, что лучше, когда мне следует использовать - 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
.
strerror
не обязательно быть поточно-ориентированной. Это глупо, но это стандарт. strerror_l
может использоваться вместо этого в качестве замены в системах POSIX 2008. strerror_r
также доступен в старых системах, но имеет действительно неприятные проблемы с некоторыми системами, имеющими его несовместимые версии.
perror
добавляет '\n'
в конце, так что формат будет "%s\n"
, нет?
strerror_s
самом деле это не так уж плохо как интерфейс.
_s
мусора в стандарт было в основном игрой MS («Если вы воспользуетесь нашими интерфейсами, мы рассмотрим, как сделать так, чтобы наши продукты поддерживали ваш стандарт»), и, конечно, теперь они не следуют этому. На самом деле я согласен, что этот интерфейс сам по себе неплох. Что плохо, так это пропаганда (в виде предупреждений компилятора) о том, что большая часть стандартной библиотеки «небезопасна» и что все семейство _s
функций должно использоваться вместо стандартных.
Они делают разные вещи.
Вы используете perror()
для печати сообщения, stderr
которое соответствует errno
. Вы можете использовать fprintf()
для печати ничего к stderr
, или любой другой поток. perror()
это очень специализированная функция печати:
perror(str);
эквивалентно
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
perror(const char *s)
: печатает переданную вами строку, за которой следует строка, описывающая текущее значение errno
.
stderr
: это выходной поток, используемый для передачи ваших собственных сообщений об ошибках (по умолчанию на терминал).
Соответствующий:
char *strerror(int errnum)
: присвойте ему номер ошибки, и он вернет соответствующую строку ошибки.
perror () всегда пишет в stderr; strerr (), используемый вместе с fprintf (), может писать в любой вывод, включая stderr, но не исключительно.
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
Кроме того, perror накладывает свой собственный текст в формате «текст: описание ошибки».
Функция Perror требует больше времени для выполнения, вызов переходит из пользовательского пространства в пространство ядра, тогда как вызовы fprintf отправляются с api на ядро
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.