The Standard Error Device

Oh, I could have fun with the term “standard error device.” It could be any PCs running Windows 8. [rimshot] See? Tech humor! It’s nerdy, but that’s not the point of the standard error device with regards to C programming.

In C, as well as other programming languages, three standard I/O devices are available:

stdin for standard input
stdout for standard output
stderr for error message output

The stdin and stdout devices are traditionally mapped to the keyboard and screen, respectively. In the olden days, these devices were a teletype. Anyway, input and output from these devices can be redirected. Input can flow from a file, for example, and output can be sent to a file or to another program, where it becomes standard input.

The stderr device cannot be redirected. It’s always mapped to the same gizmo, which on modern computers is the terminal window. This device generates error messages or other text a programmer wants displayed and not sent elsewhere.

When you use any of C standard I/O library functions, they default to stdin and stdout for input and output:

#include <stdio.h>

int main()
{
    printf("Here is Line 1\n");
    printf("Here is Line 2\n");
    printf("Here is Line 3\n");

    return(0);
}

This code generates three lines of text. The printf() statement uses the stdout device by default. Here’s the sample run:

Here is Line 1
Here is Line 2
Here is Line 3

This code is identical to the following:

#include <stdio.h>

int main()
{
    fprintf(stdout,"Here is Line 1\n");
    fprintf(stdout,"Here is Line 2\n");
    fprintf(stdout,"Here is Line 3\n");

    return(0);
}

In this example, the fprintf() function replaces printf(). It requires a stream argument before the format string, which can be the handle of an open file or one of the standard I/O devices. In C, stdout is accepted as a stream argument, always open for every program you run, as are stdin and stderr. So in this example, the strings are sent to the “file” stdout. The code’s output is the same.

In the next example, I changed the second fprintf() statement to use the stderr output device instead of stdout:

#include <stdio.h>

int main()
{
    fprintf(stdout,"Here is Line 1\n");
    fprintf(stderr,"Here is Line 2\n");
    fprintf(stdout,"Here is Line 3\n");

    return(0);
}

Again, the output is the same, but unlike stdout, stderr output cannot be redirected to another device. When I run the code in a terminal window and redirect the output elsewhere, I see only the text generated by the second fprintf() statement:

$ ./a.out > /dev/null 
Here is Line 2

Above, the program (named a.out) sent output the /dev/null device, which is a “door to nowhere” in the Unix operating system. (In Windows, use > nul.) The first and third fprintf() statement’s output meanders off in to the null device, but because the second fprintf() statement sends it output to stderr, it shows up in the terminal window.

In my code, I use the stderr device to output error messages. Especially for programs I write where I know the output is immediately fed into another program, it’s important that I see those error messages directly. Output to stderr guarantees that they show up, but the output isn’t without its quirks.

Because I/O in C is buffered, it’s common that an error message sent to stderr appears out of sequence with other text sent to standard output. I tried to replicate this peculiarity with a sample program, but it takes too much code to make it work consistently. Still, it’s possible for an error message to show up earlier than other text sent to (buffered) standard output. That weird sequencing bugged me, but it’s something you must understand when you use stderr to generate error output.

3 thoughts on “The Standard Error Device

  1. “Because I/O in C is buffered, it’s common that an error message sent to stderr appears out of sequence with other text sent to standard output.”

    Would fflush(stderr) immediately after fix this problem?

  2. The way I see the problem, you would use fflush(stdout) before using any statements that direct output to stderr. The problem I’ve seen is that the error message appears in the midst of standard output text, which is what makes it difficult to spot. I see this only in longer code that does a lot of processing. That’s when I believe the buffering gets all tangled. But you’re correct, flushing either stream would generate the immediate output. In my example, you’d want to flush stdout first.

  3. By the way, as a reader pointed out on LinkedIn, you can redirect output sent to the standard error device. You must specify the value 2 before the redirection symbol, >, as in ./a.out 2> error.log

    I’m aware of this output redirection override. In fact, the default for output redirection is really 1>, though the 1 is optional. Plus – and this is news to me – this type of output redirection for the stderr device also works in Windows! I learn something new every day.

Leave a Reply