13

I am jumping from C into C++ with the help of the book C++ Primer (5th edition) where the author states the following:

Programmers often add print statements during debugging. Such statements should always flush the stream. Otherwise, if the program crashes, output may be left in the buffer, leading to incorrect inferences about where the program crashed.

But posts online suggest otherwise; some say constant flushing of the buffer is bad for the program and causes performance issues.

My questions:

  1. When should you use std::endl?
  2. Is the author wrong or did I misunderstand any part of what he stated?
  3. Can you give any real-world scenarios where flushing the output stream is necessary?

P.S.

  1. What does flushing the buffer mean?
5
  • 11
    Why would you care about performance of statements that are only executed during debugging? Commented Feb 23, 2016 at 15:04
  • The answer to #3 is right there in what you quoted: "if the program crashes, output may be left in the buffer, leading to incorrect inferences about where the program crashed." Commented Feb 23, 2016 at 15:06
  • 4
    Note that the easiest way to flush is to use std::cerr to begin with. Commented Feb 23, 2016 at 15:12
  • Remember the author is only talking about debugging output, not general program output which should usually simply use '\n'. Commented Feb 23, 2016 at 15:35
  • 1
    In addition to Marc Glisse's comment, I'd like to recommend std::ostream& debug = std::cerr; - makes it easier to spot debug output. Commented Feb 24, 2016 at 9:54

6 Answers 6

15

Point 4 and Point 3

Starting with point 4 because everything else hinges on it and point 3 because it is tightly related.

When you flush the stream, you are taking all data stored by the stream and writing it to the underlying medium represented by the stream.

When it is flushed it is done, committed and ready to be observed by the outside world (More or less. The operating system and the hardware backing the stream may also delay the write, but there isn't much you can do about that). You can't read it until it has been flushed. If it's never flushed, you can't read it.

The thing is you do not want to write to IO very often because anything that goes out of the CPU takes an ungodly amount of time compared to that which stays inside the CPU. Tens of thousands of times slower sometimes. Inside the CPU you have gigahertz and parallel buses moving data 32 or more bits at a time. Outside you have megahertz often moving a single bit at a time.

Take a file as a classic example. Not only is drive access running at a fraction of a speed of the CPU, but if every byte goes directly to a disk, then for every byte you may have to

  1. find that byte's analogue on the disk.
  2. load the sector around that byte into memory. So instead of moving one byte, you may be moving a few hundred or thousand. Usually 512 bytes or 4096 bytes.
  3. write the byte into the sector in memory
  4. write the sector in memory back to the disk

Brutal. Imagine doing this a few hundred or a few thousand times to write a single string. But what if you only wrote the string when it got too big to hold or you were done? What if you wrote in sectors rather than bytes? Then you could

  1. find the sector on the disk.
  2. write the buffered sector to the disk

One operation for potentially thousands of byte in one shot.

Point 2

Point 2 goes back to point four/three's you can't read what you don't flush. If you want to see a particular output on the screen and you want to see it now, you flush. If you want to get a debug message out before the program crashes, and likely terminates without getting those last few absolutely essential messages onto the screen, you flush. History is full of programmers looking in the wrong place for a bug because they didn't get those last few unflushed error messages.

You are trading program speed for the relative certainty that you will see an important message when you need to see it.

Point 1

Point 1 calls back to point 2. std::endl is both an end of line and an instruction to flush the stream. You use it sparingly and only when you need both an end of line and a flush. If you don't need a flush, just send and end of line: '\n'.

Take Pete Becker's advice and use std::cerr for errors and debugging where possible. That's what it was built for. It operates on brute force and ignorance. It's painful. It's slow. And it almost always works.

Sign up to request clarification or add additional context in comments.

2 Comments

what is the "underlying medium" in the stream?
Depends on the stream. An fstreamrepresents a file as the underlying medium. cin and cout sit atop a console, and that console could read or write to just about anything, but usually the screen, a serial port or a network socket. stringstream's medium is a block of memory.
11

Debug output should be written to std::cerr; it's unit buffered, so every character gets flushed. There is rarely a need for std::endl, and getting in the habit of using it will lead to mysteriously slow code. Just use '\n' unless you know you need to flush the buffer.

Comments

5

By default std::cout is linked to stdout, which is...

fully buffered if and only if the stream can be determined not to refer to an interactive device.

(C99, 7.19.3 Files, paragraph 7.)

This means, if your output is sent to terminal, std::endl vs. "\n" makes no difference in the first place. ;-)


Regarding your actual question:

Both is true:

  • unflushed output buffers can lead to incorrect inferences about where the program crashed
  • flushing of output buffers affects performance

This only becomes a problem once you add "always".

When should you use std::endl?

When you want to flush the buffer.

Is the author wrong or did I miss understand any part of what he stated?

I think absolute quantifiers like "always", "all", "never" etc. should be taken with a grain of salt as far as style / design / etc. is concerned.

(Exception: Never invoke undefined behaviour. ;-) )

Can you give any real world scenarios for actual need of flushing the output stream?

Whenever not having the latest output actually appear would not be acceptable. Whether this is the case in any given scenario is a judgement call.

Personally, I would consider production / transaction logs to be more critical than debug logs...

Comments

1

Both the author and the posts are right.

stream << std::endl is actually stream << '\n' << std::flush. Explicit flushing has performance drawbacks, and this is why you shouldn't use it in performance-critical situations. You rarely think about such negligible performance issues while debugging, so it actualy is a good practice to explicitly flush debug output.

Comments

0

1) When should you use std::endl ?

When you want to be sure that the buffer is immediately flushed.

2) Is the author wrong or did i miss understand any part of what he stated?

No, the author is correct, and so are you.

3) can you give any real world scenarios for actual need of flushing the output stream?

When a particual string is written to the stream lots of times in a short amount of time std::endl might indeed cause performance loss because of the needless flushing of the buffer every time. However, when it comes to printing lines that are added for the sole purpose of debugging you should always flush the buffer. Then again, if you're debugging an application with just print lines without using a debugger you're doing something wrong in the first place.

Comments

-9

You should never use std::endl. This is a cargo-cult which must vanish. Gives you nothing but performance drawback. Just make it a muscle memory: always "\n", never std::endl.

23 Comments

"never" is in the same league as "always": I don't like absolute statements in contexts like these, they do more damage than good. Not my downvote though, you already got your share. ;-)
"...except where necessary for downward compatibility". ;-) "Never invoke UB" is better. ;-)
@SergeyA I want shared pointer which points to memory shared by several processes and destroys object when all processes stop using this object. IS there any already implemented smart pointer? What to do with library implementers? Function I posted was just an example. There are many more (usually to get some system info)
@SergeyA All your "never"'s only apply to low-skilled programmers, who find it easier to learn a thousand of "never"-rules instead of learning how C++ works. Not all C++ programmers are that silly.
@SergeyA: std::shared_ptr for inter-process shared memory? And yes, I agree a library implementor shouldn't ask such a question. But why should anybody first learn absolute rules, always do this, never do that, then have to unlearn them again as he becomes more skillful (casting doubt on his tutors in the process)? I think even beginners can handle a "don't, unless you really know what you're doing".
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.