Buffered cout and flush confusion

I was reading up on std::flush and stumbled upon the following:

"By default, std::cout is buffered, and the actual output is only printed once the buffer is full or some other flushing situation occurs (e.g. a newline in the stream). Sometimes you want to make sure that the printing happens immediately, and you need to flush manually."

-from http://stackoverflow.com/questions/14105650/how-does-stdflush-work

1
2
3
std::cout<<"test";
Sleep(5000);
return 0;


This prints test even before the call to Sleep is executed, with no need to flush. Why?
Last edited on
Hi,

Maybe the compiler is smart enough to recognise the call to Sleep as a reason to flush implicitly.

In the previous SO answer:

SO wrote:
The remaining question is: When would you flush a stream? The answer is: When the characters should be written to the external destination!


So your situation looks like it needs a flush. Is there any hardship in doing this?

std::cout<<"test\n";

Or if you were particularly worried:

std::cout<<"test" << std::flush;

http://en.cppreference.com/w/cpp/io/manip/flush

Output to std::cerr is automatically flushed, and control of flushing can be done with std::unitbuf

http://en.cppreference.com/w/cpp/io/cerr
http://en.cppreference.com/w/cpp/io/manip/unitbuf

Hope this helps a bit :+)
"Flushing" a stream and stream buffers are vastly over-simplified, causing confusion like this.

Sleep
Sleep() has absolutely no relationship with I/O processes (besides blocking the main window procedure from receiving messages).

Flushing and buffers
To "flush" is to flush (or empty) the stream's buffer (character cache).

When you cout.flush() you are only flushing std::cout's stream buffer.

Further, the SO answer isn't entirely correct. Once you write the characters to the stream (by flushing your end of the stream) there are other buffers that may be involved. Whether or not the data gets to its final destination right away is not up to you after that point.
If you must force or guarantee that data makes it to its final destination you must use platform-specific functions, assuming they are available.

That means that the console stream "flushes" (displays output) based upon the terminal setup. On modern Windows, that's whenever it gets input (your program's output).

tied streams
Standard C++ streams have a concept of being "tied" to other streams. What that means is that before any I/O is performed all "tied" streams are flushed.

The std::cout stream is "tied" to std::cin and std::cerr, so it is automatically flushed if you try to do I/O on either.

standard streams are special anyway
The standard streams (cin, cout, cerr) are unique in other ways. Their behavior is modified by the C standard I/O streams (stdin, stdout, stderr) machinery, and synchronized to them by default. Further, their function may be especially modified by any combination of OS, compiler, and compiler version.

What this means is that you may have to deal with some weird stuff using them that you wouldn't with any other stream.

Hope this helps.
In general, std::cout is not buffered by default: as long as sync_with_stdio is active, every byte written to std::cout's buffer is immediately pushed to stdout's buffer.

stdout is line-buffered by default in POSIX, so if you run the above program using gcc on linux (with C++ sleep instead of Windows Sleep), you will not observe the output until after the pause.

Based on "Sleep(5000);" however, this is using Windows. There, C I/O streams are not buffered (at least not in VS 2013 I have on this computer) You can observe that by replacing std::cout << "test"; with printf("test");. The output still appears immediately.

You can still make Windows delay the output, if you enable buffering on stdout:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <cstdio>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

int main()
{
	char buf[BUFSIZ];
	std::setbuf(stdout, buf);
	std::cout << "test";
	// std::fflush(stdout); // <- uncomment to see the text before the pause
	Sleep(5000);
	std::fflush(stdout);
	std::setbuf(stdout, NULL); // don't let the stream outlive the buffer
}


Actually, that demo won't let you observe the effect of std::flush, since flush only moves cout's buffer (which it doesn't even have by default) into stdout's buffer, where the output sits until flushed using std::fflush or implicit means.

To obseve std::flush, give std::cout its own buffer and disconnect it from C I/O streams:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

int main()
{
	char buf[BUFSIZ];
	std::ios::sync_with_stdio(false);
	std::cout.rdbuf()->pubsetbuf(buf, sizeof buf);
	std::cout << "test";
	//std::cout << std::flush; // <- uncomment to obseve the output before the pause
	Sleep(5000);
	std::cout << std::flush;
	std::cout.rdbuf()->pubsetbuf(nullptr, 0); // don't let the stream outlive the buffer
}
Last edited on
Thank you all for the detailed explanations - especially your demo Cubbi

A good reminder why I like this site better than SO
Topic archived. No new replies allowed.