6

I had read that both perror() and printf() write to the terminal screen. But perror() writes to stderr while printf() writes to stdout. So, to print errors why is perror() used when printf() can do it.

6 Answers6

7

printf() cannot write to stderr. fprintf() can. perror() always does.

There is no requirement that writing to either stdout or stderr writes to a terminal screen - that is up to the implementation (since not all systems even have a terminal). There is also no requirement that writing to stdout and stderr results in writing to the same device (e.g. one can be redirected to a file, while the other is redirected to a pipe).

perror() will be implemented with built-in knowledge of the meanings of error codes, represented by the static errno, which is used by various functions in the standard library to report error conditions. The meanings of particular values are implementation defined (i.e. they vary between compilers and libraries).

Peter
  • 35,646
  • 4
  • 32
  • 74
2

Because there could be configurations where you want stderr printed to the console but the other output not printed at all (for example, to remove verbosity). In other cases you may need to redirect stderr to write to a file, this is useful when you are in production and that file can be used to understand what went wrong on a remote computer you can't debug yourself.

In general, you gain more control on how console outputs are treated depending on their type.

See this answer to understand how you can do stream redirection in code.

Or, see this link on how you can force stream redirection to file or ignore a stream on an already compiled program (while invoking it in bash)

Community
  • 1
  • 1
GavinoGrifoni
  • 743
  • 2
  • 12
  • 33
2

In addition to other answers, you might use fprintf(3) on stderr and errno(3) with strerror(3) like

 fprintf(stderr, "something wrong: %s\n", strerror(errno));

On GNU libc systems (many Linux systems), you could use instead %m conversion specifier instead:

fprintf(stderr, "something wrong: %m\n");

You conventionally should output error messages to stderr (see stderr(3)); see also syslog(3) to use system logging.

Don't forget to end the format string with \n since stderr is often line buffered (but sometimes not) or else use fflush(3)

For example, you might want to show both the error, the filename and the current directory on fopen failure:

char* filename = somefilepath();
assert (filename != NULL);
FILE* f = fopen(filename, "r");
if (!f) {
   int e = errno; // keep errno, it could be later overwritten
   if (filename[0] == '/') /// absolute path
      fprintf(stderr, "failed to open %s : %s\n", filename, strerror(e));
   else { // we also try to show the current directory since relative path
      char dirbuf[128];
      memset (dirbuf, 0, sizeof(dirbuf));
      if (getcwd(dirbuf, sizeof(dirbuf)-1)) 
         fprintf(stderr, "failed to open %s in %s : %s\n", 
                 filename, dirbuf, sterror(e));
      else // unlikely case when getcwd failed so errno overwritten
         fprintf(stderr, "failed to open %s here : %s\n", 
                 filename, sterror(e));
   };
   exit(EXIT_FAILURE); // in all cases when fopen failed
 }

Remember that errno could be overwritten by many failures (so we store it in e, in the unlikely case that getcwd fails and overwrite errno).

If your program is a deamon (e.g. has called daemon(3)) you'll better use system log (i.e. call openlog(3) after calling daemon) since daemon can redirect stderr to /dev/null

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

There are three standard stream stdin stdout stderr. You can refer to know what is important of different stream.

For error messages and diagnostics ,stderr is used , to print on stderr Perror is used. printf can not do that. Perror is also used to handle errors from system call

fd = open (pathname, flags, mode);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}

You can refer more about this in book The linux programming interface

void perror(const char *s)

Perror prints message in following sequence :

argument of s , a colon , a space , a short message concerning error whose error code currently in errnoand newline

In standard C if s is null pointer than only message will be printed . other things will be ignored

To understand more you can also refer page 332 of The complete reference C

Punit Vara
  • 3,744
  • 1
  • 16
  • 30
1

A big advantage of using perror():

It is sometimes very useful to redirect stdout into /dev/null to only have access to errors since the verbosity of stdout might hide the errors that we need to fix.

ndrrr
  • 36
  • 4
-3

perror

The general purpose of the function is to halt the execution process due to an error. The error message produced by perror is platform-depend. You can also print your own error message also.

printf

The general purpose of the function is to print message user defined and continue the execution.

Vineet1982
  • 7,730
  • 4
  • 32
  • 67
  • 4
    "*The general purpose of the function is to halt the execution process due to an error.*". `perror()` does *not* halt the program at all. – alk Dec 05 '15 at 09:10
  • Err, so what please is the intention of your wording then? – alk Dec 05 '15 at 09:13
  • 1
    @alk it is generally used to halt the process e.g. perror(errno);exit(1); – Vineet1982 Dec 05 '15 at 09:23
  • 2
    Well, then perror isn't used to halt the process. In your example, it's used together with halting the process. Thoug, I'm not sure I'd say that it's generally used only in that case. So please, don't mix perror with halting processes. – Anders Dec 07 '15 at 07:34