I'm learning c and I got stuck in some codes as below from a tutorial.
#include <stdio.h>
int main() {
fprintf(stdout, "This is to stdout. ");
fprintf(stderr, "This is to stderr. ");
fprintf(stdout, "This is also to stdout. ");
}
and the result they got is
This is to stderr. This is to stdout. This is also to stdout.
which is out of order
but what I got is
This is to stdout. This is to stderr. This is also to stdout.
which is in order.
So that's so weird, Why I got a different result?
(the tut I refer to is https://www.journaldev.com/39049/fflush-in-c)
Maybe in your implementation, stdout is unbuffered. Check your documentation.
You may want to try setvbuf() to revert stdout to line-buffered: use, for example, setvbuf(stdout, 0, _IOLBF, 1000); right at the beginning of main() before any other use of stdout.
Usually stdout is line-buffered and stderr is unbuffered.
unbuffered : data is sent, by the OS, from the stream to the device as soon as it is available.
line-buffered: data is sent to the device when a newline (or a limit) is reached.
fully buffered: data is sent to the device when the buffer is full.
fprintf(stdout, "hello"); // "hello" is kept in buffer because no newline
fprintf(stderr, "again"); // "again" is sent to the device immediately
fprintf(stdout, "world"); // "world" is kept in buffer
// ...
return 0; // buffer (now containing "helloworld") is sent to the device at program completion
Related
When I run the following C code on a Linux system:
printf("This is sentence 1. ");
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
I get the output in a wrong order:
This is sentence 2.
This is sentence 1.
I understand that this happens because 'printf' sends the data to a buffer in the user space, and it takes some time to get to the kernel space, while 'write' sends the data immediately to the cache buffer in the kernel space.
A way to fix this is by flushing the data from user-space buffer to kernel-space buffer this way:
printf("This is sentence 1. ");
fflush(stdout);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
And then the correct output is received:
This is sentence 1. This is sentence 2.
Another way that I tried to solve this issue is by trying to get the stdout stream from the STDOUT_FILENO fd:
FILE *file = fdopen(STDOUT_FILENO, "w");
printf("This is sentence 1. ");
fflush(file);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
But, I get the output in the wrong order:
This is sentence 2.
This is sentence 1.
In order to make sure that STDOUT_FILENO is a fd that represents stdout, I converted stdout to a fd:
int fd = fileno(stdout);
if(fd == STDOUT_FILENO)
printf("fd == STDOUT_FILENO == %d\n", fd);
And received the expected output:
fd == STDOUT_FILENO == 1
So, the question is why when converting STDOUT_FILENO to a stream that should be equivalent to stdout, the 'fflush' function doesn't work? Is there a problem with the way I use 'fdopen'?
The buffer is a property of the stdio stream, that is, the FILE structure. printf is always printing to stdout, so it's the stdout stream you need to call fflush on. When you wrote
FILE *file = fdopen(STDOUT_FILENO, "w");`
, that gave you a second, completely independent FILE stream, with its own buffer. But you don't print anything to that stream, so falling fflush on it accomplishes nothing, and meanwhile, the text you printfed to stdout remains unflushed.
If you've got buffered output on stdout, it's stdout you must call fflush on. (Or, alternatively, add a \n at the end of the string you print with printf, since stdout is typically line-buffered, at least if it's going to a terminal.)
In this:
FILE *file = fdopen(STDOUT_FILENO, "w");
printf("This is sentence 1. ");
fflush(file);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
printf does not send anything to file. It writes to stdout.
Each FILE object contains its own buffer (whether directly or via pointer to allocated memory). When you execute printf("This is sentence 1. ");, it writes to the buffer in the stdout FILE. When you fflush(file);, it flushes the buffer in file.
To make this work, you could write fprintf(file, "This is sentence 1. ");, since that will write to the buffer in file, and fflush(file); will flush it.
I am reading 'UNIX Network Programming: The Sockets Networking API' and in the example code they have an error handling function which contains the following lines:
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
Where buf contains the error description. I don't understand why fflush is used on stdout on the first line and why the comment explains the reason for its use.
This is because of buffering. Stdout and stderr are usually buffered differently. Stdout is usually line buffered, meaning it will not display output until it sees a newline. Stderr is usually unbuffered and will print immediately, the thinking is you should see error messages pronto.
But they both go to the same place, the terminal. This is what it means by /* in case stdout and stderr are the same */. They usually are. But because they're buffered differently this can lead to them being displayed out of order.
Consider this code. Note the lack of a newlines.
#include <stdio.h>
int main() {
fprintf(stdout, "This is to stdout. ");
fprintf(stderr, "This is to stderr. ");
fprintf(stdout, "This is also to stdout. ");
}
You'd expect the output to be:
This is to stdout. This is to stderr. This is also to stdout.
But it isn't. It's out of order.
$ ./test
This is to stderr. This is to stdout. This is also to stdout.
The output to stderr is displayed immediately, it is unbuffered. While stdout has to wait until the stdout buffer is flushed by a newline. There is no newline, so it is flushed when the program exits.
By flushing stdout before you use stderr you ensure that the output comes in the right order regardless of buffering.
#include <stdio.h>
#include <unistd.h>
int main() {
fprintf(stdout, "This is to stdout. ");
fflush(stdout);
fprintf(stderr, "This is to stderr. ");
fprintf(stdout, "This is also to stdout. ");
}
$ ./test
This is to stdout. This is to stderr. This is also to stdout.
This ensures that error messages come out in the right order along with normal messages. This avoids confusion about what error message applies to what part of the program.
If stdout and stderr point to the same file, you have to be sure that whatever is in the stdout buffer is written first.
The code is as follows:
printf("u");
write(STDOUT_FILENO, "m", 1);
printf("d\n");
output: mud
Can someone explain why the output is printed in this order?
The standard output is line buffered by default, that means printf("u"), will only put the "u" in its buffer, until a fflush or a new line character is seen. To see the output in order, try this:
printf("u");
fflush(stdout);
write(STDOUT_FILENO, "m", 1);
printf("d\n");
printf stores "u" in a buffer. write writes data to the underlying filedescritor. The next printf puts "d\n" in the buffer. At some point in the future (either when the program exits, or when you call printf enough that the buffer is full), the buffer will be written to the underlying file descriptor.
Output via the standard C streams is buffered. The first call to printf stored u into the buffer, while the second line outputs an m directly to the system's standard output file handle via the write system call, finally the second call to printf stores d and a line feed in the buffer and flushes the buffer to the system standard output handle, either because output is line buffered (which is usually the default if the FILE* is associated with a terminal) and \n causes the flush or because the stream is flushed upon program normal termination.
stderr is unbuffered by default, try this:
fprintf(stderr, "u");
write(STDERR_FILENO, "m", 1);
fprintf(stderr, "d\n");
I have this simple peace of code :
#include <stdio.h>
int main()
{
fprintf(stdout , "stdout \n");
fprintf(stderr , "stduerr \n");
return 0;
}
Output:
stdout
stderr
I know that stdout is buffered and stderr is not and know a bout newline flushing
the result on Windows and netbeans is :
stdout
stderr
the result using mac and Eclipse :
stderr
stdout
and Want to know why ...
Thanks a lot ...
stdout by default (on your system anyways) is line buffered, meaning it will flush either when you flush it, or when you put a newline character '\n' in it, which you do here:
fprintf(stdout , "stdout \n");
More on the buffering of stdout:
If stdout is known to not refer to an interactive device, the stream
is fully buffered. Otherwise, it is library-dependent whether the
stream is line buffered or not buffered by default (see setvbuf).
Source
With stdio(3) output streams that refer to terminal devices are line buffered like stdout, while stderr is not buffered.
The program above exits immediately after fprintf, so stdout is flushed then.
If you want to see the differences in behavior, redirect the stdout and stderr to a file, and add a few more fprintf lines.
As others already noted, you will get the result you expected if you use
fprintf(stdout, "STDOUT");
fprintf(stderr, "STDERR");
This is because the default Linux terminal stdout is line buffered while stderr is not buffered.
You will need to flush stdout or to manually print a '\n' to stdout before the print to stderr. Then you will see it before the stderr message.
Note that it is also possible to turn off buffering for stdout.
#include<stdio.h>
#include <unistd.h>
int main(){
while(1)
{
fprintf(stdout,"hello-out");
fprintf(stderr,"hello-err");
sleep(1);
}
return 0;
}
On compiling this programme in gcc and on executing it only prints hello-err and not hello-out.Why is that so?Can someone please explain the reason behind it?
If you add a '\n' to your message it will (or should), ie. "hello-out\n".
The reason being is that stdout is buffered in order to be more efficient, whereas stderr doesn't buffer it's output and is more appropriate for error messages and things that need to be printed immediately.
stdout will usually be flushed when:
A newline (\n) is to be printed
You read in from stdin
fflush() is called on it
EDIT: The other thing I wanted to add before my computer crashed...twice...was that you can also use setbuf(stdout, NULL); to disable buffering of stdout. I've done that before when I've had to use write() (Unix) and didn't want my output to be buffered.
It doesn't always print out the output to stdout because by design stdout is BUFFERED output, and stderr is unbuffered. In general, the for a buffered output stream, the stream is not dumped until the system is "free" to do so. So data can continue buffering for a long while, before it gets flushed. If you want to force the buffer to flush you can do so by hand using fflush
#include<stdio.h>
#include <unistd.h>
int main(){
while(1)
{
fprintf(stdout,"hello-out");
fflush(stdout); /* force flush */
fprintf(stderr,"hello-err");
sleep(1);
}
return 0;
}
Update: stdout is linebuffered when connected to a terminal, and simply buffered otherwise (e.g. a redirect or a pipe)
You forgot newlines (noted \n) in your strings. Or you need to call fflush(NULL); or at least fflush(stdout); before sleep(1);
And fprintf(stdout, ...) is the same as printf(...)
You need to output newlines or to call fflush because (at least on Linux) the stdout FILE buffer is line-buffered. This means that the C library is buffering data, and will really output it (using the write Linux system call) when the buffer is full enough, or when you flush it either with a new line, or by calling fflush. Buffering is needed because system calls are costly (calling write for every byte to be output is really too slow). Read also the man page of setbuf