Коли я повинен використовувати perror ("...") та fprintf (stderr, "...")?


105

Читання чоловічих сторінок та якогось коду насправді не допомогло мені зрозуміти різницю між тим, чи краще, коли я повинен використовувати - perror("...")чи fprintf(stderr, "...").

Відповіді:


113

Виклик 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.


3
ой, отримав це. Функція перора працює по-різному, залежно від значення errno. 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.
freeboy1015

6
Один деталь, strerrorщоб не бути безпечним для потоків , не вимагається. Це дурно, але це стандарт. strerror_lможе використовуватись замість цього як заміна, що випадає, на системах POSIX 2008. strerror_rтакож доступний для старих систем, але в деяких системах, що мають невідповідні версії, виникають неприємні проблеми.
R .. GitHub СТОП ДОПОМОГАЄТЬСЯ

також як нітрик, я думаю, perrorдодає '\n'наприкінці, щоб формат був "%s\n", ні?
Йенс Гуведт

1
@R .., ha, я вже маю, і наскільки я знаю, вони мені нічого не платять. А оскільки MS, здається, повністю скорочує свою підтримку C, я, зрештою, буду єдиним :) strerror_sнасправді не так вже й погано, як інтерфейс.
Jens Gustedt

2
Порізка підтримки повністю? Схоже, вони знову обдурили комітет. Перетворення їх _sсміття в стандарт в основному було грою MS ("Якщо ви приймете наші інтерфейси, ми розглянемо, як насправді зробити так, щоб наші продукти підтримували ваш стандарт"), і, звичайно, зараз вони не дотримуються. Насправді я згоден, що цей один інтерфейс сам по собі не поганий. Що погано, це пропаганда (у вигляді попереджень компілятора) про те, що більшість стандартних бібліотек є "небезпечними" і що все сімейство _sфункцій слід використовувати замість стандартних.
R .. GitHub СТОП ДОПОМОГАТИ

40

Вони роблять досить різні речі.

Ви можете використовувати 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));

12

perror(const char *s): друкує рядок, який ви надаєте йому, а потім рядок, що описує поточне значення errno.

stderr: це вихідний потік, який використовується для передачі ваших власних повідомлень про помилки (за замовчуванням до терміналу).

Відповідне:

char *strerror(int errnum): дайте йому номер помилки, і він поверне пов'язаний рядок помилки.


2

perror () завжди пише в stderr; strerr (), який використовується разом з fprintf (), може записувати на будь-який вихід - включаючи stderr, але не виключно.

fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")

Крім того, перор нав'язує свій власний текст "текст: опис помилки"


-2

Функція Perror займає більше часу для виконання виклику, йде від простору користувача до простору ядра, коли виклики fprintf переходять до api до ядра

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.