TheJavaFan
TheJavaFan

Reputation: 339

The consequences and pros/cons of flushing the stream in c++

I have recently read an article which stated that using \n is preferable to using std::endl because endl also flushes the stream.
But when I looked for a bit more information on the topic I found a site which stated:

If you are in a situation where you have to avoid buffering, you can use std::endl instead of ‘\n’

Now here comes my question: In which situation is it preferable not to write to the buffer? Because I only saw advantages of that technique. Isn't it also safer to write to the buffer? Because it is smaller than a hard drive it will get overwritten faster than data that is stored on the HD (I am not sure if this is true).

Upvotes: 25

Views: 3399

Answers (5)

Marco A.
Marco A.

Reputation: 43662

When buffering occurs you will have no guarantees that the data is immediately received before a flush occurs. Under particular circumstances you might experience wrong output ordering and/or loss of information/debug data, e.g.

int main() {
   
    std::cout << "This text is quite nice and might as well be buffered";
    raise(SIGSEGV); // Oh dear.. segmentation violation
    std::cout << std::endl;
}

Live Example

Output:

bash: line 7: 22235 Segmentation fault      (core dumped) ./a.out

the above will not print any text since the buffering prevented the right output to be displayed.

Now if you simply add a flushing std::endl at the end of the buffer this is what you get

int main() {
   
    std::cout << "This text is quite nice and might as well be buffered" << std::endl;
    raise(SIGSEGV); // Oh dear.. segmentation violation
    std::cout << std::endl;
}

Live Example

Output:

This text is quite nice and might as well be buffered
bash: line 7: 22444 Segmentation fault      (core dumped) ./a.out

This time the output is visible before the program termination.

Implications of this fact are manifold. Purely speculative: if the data were related to a server log, your app could have crashed before the actual logging.

Upvotes: 20

Petr
Petr

Reputation: 9997

It will be preferable in any situation in which you want the output to actually appear exactly when it was supposed to appear.

A simple example:

#include <iostream>
int main() {
    std::cout << "Please enter your name: " << std::endl;
    std::string name;
    std::cin >> name;
    ...
}

With buffering, no text will appear on screen before the user is expected to type his/her name, so the user will be confused. (Note that in fact it might be really difficult or impossible to get this example run with buffering fully enabled, as C++ might take special measures to flush std::cout before any input from std::cin, see Why do we need to tie std::cin and std::cout?. But this is just a theoretical example: in case the buffering is fully enabled, the user will not see the prompt.)

Such a situation can occur from time to time, though it might not be very often. Consider writing to a pipe to interact with another process. Or even if your program writes to log file and you personally look into the log file from time to time to see how it runs --- in case of buffering, you usually will not see the output that has been printed from program, but still stays in the buffer yet.

Another important situation to account for --- if your program severely crashes, the buffer contents might not end on the hard drive at all. (I expect the stream destructors to flush the buffer, but a crash can be so severe that no destructors will be called at all.)

Upvotes: 11

Pete Becker
Pete Becker

Reputation: 76428

I hope you've lost the link to that site that you found. std::endl does not avoid buffering. It flushes whatever is in the buffer. If you need to avoid buffering, use setf(ios_base::unitbuf). That sets the stream to flush after each insertion. That's the default setting for std::clog. The reason for doing this is that the less stuff being held in the buffer, the greater the chance that critical data will have been written to the stream when the program crashes.

Flushing also matters for interactive programs: if you write a prompt to std::cout, it's a Good Thing if that prompt shows up on the display before the program starts waiting for input. That's done automatically when you use std::cout and std::cin, unless you've messed with the synchronization settings.

Many programmers seem to use std::endl as a fancy way of spelling '\n', but it's not. You don't need to flush the output buffer every time you write something to it. Let the OS and the standard library do their jobs; they'll take care of getting the output to the appropriate place in a timely manner. A simple std::cout << '\n'; is all that's needed to put a newline into the output, and sooner or later, that will show up on the display. If you need to have it show now, typically because you've written all of the output for the time being and don't want to leave the displayed information incomplete, use std::endl after the last line of the output.

Upvotes: 5

user1084944
user1084944

Reputation:

First, a bit of revisionist history.

In the old days, when everybody used stdio.h library to do I/O, text that was viewed interactively was typically line buffered (or even unbuffered), and text that was not was fully buffered. So, if you output '\n' to the stream, it would "always" do the Right Thing: lines users were looking at get flushed and seen immediately, and lines getting dumped to file get buffered for maximum performance.

Unfortunately, it isn't actually always the Right Thing; the runtime cannot always predict how users actually want to view the output of your program. One common trap is redirecting STDOUT -- people get used to running their program in a console and seeing the output (with its line-buffered behavior) in the console, and then for whatever reason (e.g. long running job) they decide to redirect STDOUT to a file, and are promptly surprised by the fact the output is no longer line-buffered.

I have seen weeks of supercomputer time wasted for this reason; the output was infrequent enough that the buffering prevented anyone from being able to tell how the job was progressing.

C++'s iostream library, however, was designed to make it easy to do the Right Thing here. Except when synchronizing with stdio, it doesn't do this funny "maybe line-buffered maybe fully-buffered" thing. It always uses full buffering (except when you do unbuffered stuff, of course), and if you want things flushed on newline, you do so explicitly.

So if you're dumping a bunch of formatted text to a file that people won't be looking at until it's done, you write \n for your line breaks.

But if you're writing text people might actually want to look at while you're writing it, you use std::endl for your line breaks, and it gets displayed immediately. And if you're writing several lines at once, you can even do better: use '\n' for the intermediate line breaks and std::endl for the final one (or '\n' and std::flush). Although in this setting performance usually doesn't matter so it's usually fine to just use std::endl for all of the line breaks.

Upvotes: 10

Drew Dormann
Drew Dormann

Reputation: 63839

It is preferable to flush the buffer if you need the target of your stream to receive the data before the stream is closed.

A real-life example would be an application log, written from a stream that's always open... You may want to look at this log while the program is still running.

Upvotes: 10

Related Questions