Why is the output order different from the call order when using fprintf with stdout or stderr?
My environment is Debian GNU/Linux 11.
The fprintf
function with param stdout
or stderr
gives unexpected output order.
int main() {
std::cout << "Hello, World!" << std::endl;
fprintf(stderr, "22222\n");
fprintf(stdout, "111\n");
printf("3333 \n");
printf("44444 \n");
return 0;
}
I've run this many times and got many different results:
//①
22222
Hello, World!
111
3333
44444
//②
Hello, World!
111
3333
44444
22222
What's the reason? Or, I want to understand the phenomenon, what knowledge do I need?
On my understanding, the output log should like this:
//③
Hello, World!
22222
111
3333
44444
About the two output logs of ①/②, I don't understand.
I think log ③ is right, but it does not appear, that makes me wonder.
The output is never like ② because output to stderr
isn't buffered so 22222
will be flushed immediately and would be before any other numbers. Output to stdout
may be line-buffered (default on Linux) or full-buffered (default on Windows)
The output shouldn't be like ① either because you're already flushing with std::endl
in the first line, hence Hello, World!
would be printed first. That's why never use std::endl
unless you really know what it's doing. Always use std::cout << "Hello, World!\n";
. See "std::endl" vs "\n"
③ should be the correct output because on Linux it'll flush on every statement, and on Windows the final 3 writes to stdout
are flushed at once at the end
Hello, World!
22222
111
3333
44444
If there are any differences then there are some issues with your stdlib
By default the legacy and C++ streams are also synchronized so it's possible to mix both types of streams with some performance penalty. You can disable it like this
std::ios::sync_with_stdio(false);
to get better performance but now the Hello, World!
string can be printed anywhere