Reading the man pages and some code did not really help me in
understanding the difference between - or better, when I should use - perror("...")
or fprintf(stderr, "...")
.

- 763
- 7
- 22
- 32

- 2,227
- 2
- 18
- 15
-
Why would you want to print `...: No such file or directory` for example – user16217248 Feb 01 '22 at 22:13
5 Answers
Calling perror
will give you the interpreted value of errno
, which is a thread-local error value written to by POSIX syscalls (i.e., every thread has it's own value for errno
). For instance, if you made a call to open()
, and there was an error generated (i.e., it returned -1
), you could then call perror
immediately afterwards to see what the actual error was. Keep in mind that if you call other syscalls in the meantime, then the value in errno
will be written over, and calling perror
won't be of any use in diagnosing your issue if an error was generated by an earlier syscall.
fprintf(stderr, ...)
on the other-hand can be used to print your own custom error messages. By printing to stderr
, you avoid your error reporting output being mixed with "normal" output that should be going to stdout
.
Keep in mind that fprintf(stderr, "%s\n", strerror(errno))
is similar to perror(NULL)
since a call to strerror(errno)
will generate the printed string value for errno
, and you can then combined that with any other custom error message via fprintf
.

- 16,831
- 17
- 68
- 94

- 31,834
- 7
- 59
- 78
-
5oh, got it.The perror function works differently depending on the value of errno. `If you use a function that effects errno then it makes sense to use perror`.If you use a function that does not effect errno and simply returns an error code you should use fprintf(stderr, fmt, ...). For example, strtol will return LONG_MAX or LONG_MIN if a string is out of range and set errno to ERANGE. So if strtol fails due to out of range, I would use perror. – freeboy1015 Aug 24 '12 at 02:22
-
8One detail, `strerror` is not required to be thread-safe. It's stupid, but that's the standard. `strerror_l` can be used instead as a drop-in replacement on POSIX 2008 systems. `strerror_r` is also available on older systems but has really nasty issues with some systems having nonconformant versions of it. – R.. GitHub STOP HELPING ICE Aug 24 '12 at 02:35
-
@R.. C11 has (will have :) `strerror_s` as a thread safe variant. – Jens Gustedt Aug 24 '12 at 07:38
-
It's an optional interface and nobody except MS is going to implement it. – R.. GitHub STOP HELPING ICE Aug 24 '12 at 12:36
-
1@R.., ha, I already have, and as far as I know they are not paying me a thing. And since MS seems to be cutting their support for C completely, at the end I will be the only one :) `strerror_s` is actually not too bad as an interface. – Jens Gustedt Aug 24 '12 at 18:28
-
2Cutting support completely? Looks like they fooled the committee again. Getting their `_s` junk into the standard was basically a game by MS ("If you adopt our interfaces, we'll consider actually making our products support your standard.") and of course now they're not following through. Actually I agree that this one interface is not bad in itself. What's bad is the propaganda (in the form of compiler warnings) that most of the standard library is "unsafe" and that the whole family of `_s` functions should be used instead of the standard ones. – R.. GitHub STOP HELPING ICE Aug 24 '12 at 18:45
-
They do rather different things.
You use perror()
to print a message to stderr
that corresponds to errno
. You use fprintf()
to print anything to stderr
, or any other stream. perror()
is a very specialized printing function:
perror(str);
is equivalent to
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));

- 37,726
- 7
- 50
- 96

- 2,227
- 2
- 18
- 15
perror(const char *s)
: prints the string you give it followed by a string that describes the current value of errno
.
stderr
: it's an output stream used to pipe your own error messages to (defaults to the terminal).
Relevant:
char *strerror(int errnum)
: give it an error number, and it'll return the associated error string.

- 552
- 3
- 10
perror() always writes to stderr; strerr(), used together with fprintf(), can write to any output - including stderr but not exclusively.
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
Furthermore, perror imposes its own text formating "text: error description"

- 29
- 2
The perror
function takes more time to perform. Its execution calls go from user space to the kernel space whereas fprintf
calls go from the API to the kernel.

- 317
- 1
- 14

- 1
- 1