Has anyone ever seen this std::endl quirk?

  • Context:
  • Thread starter Thread starter Dr Transport
  • Start date Start date
Click For Summary

Discussion Overview

The discussion revolves around an observed quirk with the use of std::endl in C++ when working with threads. Participants explore the behavior of output buffering and flushing in relation to std::endl compared to using a newline character directly.

Discussion Character

  • Exploratory
  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant notes that std::endl does not seem to behave as expected in a threaded context, while a newline character does.
  • Another suggests that std::endl may write to the output buffer but not flush it to the output stream immediately, leading to unexpected behavior.
  • Some participants propose that the issue could be related to buffer flushing and thread control, suggesting that the thread may yield control before flushing occurs.
  • It is mentioned that using "\n" is likely faster than std::endl due to the latter causing a flush every time it is called.
  • One participant expresses confusion about the flushing behavior of std::endl, noting that it is defined as a newline followed by a flush.
  • There is a discussion about the interpretation of shorthand notation in code examples, particularly regarding the use of ellipses (...).
  • Some participants agree that the flushing issue may be related to thread context switching, but the exact cause of the missing carriage return remains unclear.
  • Concerns are raised about the potential for bugs being hidden by shorthand notation in code examples.

Areas of Agreement / Disagreement

Participants express multiple competing views regarding the behavior of std::endl and its interaction with threading. There is no consensus on the exact cause of the issue or the interpretation of shorthand notation.

Contextual Notes

Some participants note that the behavior of std::endl may vary across different systems, and the discussion includes references to the flushing behavior of output buffers and the differences between newline characters on various operating systems.

Messages
2,603
Reaction score
785
Yesterday afternoon, instead of doing real meaningful work I was screwing around with <threads> on my Debian box at work. I've been spending some time looking at converting some of our codes and working on getting them parallelized better. Like most legacy codes, the parallel part was really an afterthought. So on to my question. The basic hello world via threads works pretty well but I noticed a quirk in the output. When I tried to use
Code:
 std::cout << ...  << std::endl;

to end the line and add a newline, it didn't work, but if I typed in

Code:
 std::cout << "...\n";

the next output line was on the next line. Anyone ever seen this before? The code compiles correctly without any errors, just doesn't behave as I would expect. Now I didn't try it with another program, although I did write a hello world to play with the g++ compiler previously and didn't see this issue.
 
Technology news on Phys.org
I've seen something similar to this when I was recently doing a simple program with threads, so maybe my explanation will be pertinent, or maybe not.

It's possible that the std::endl character gets written, but only to the output buffer, not to the output stream itself (the monitor). I don't know why the behavior would be different with a newline character appended directly to the string your printing, but perhaps in this case, it's one operation as opposed to a separate call to count << std::endl; .

Just a guess...
 
  • Like
Likes   Reactions: jedishrfu
You could try repeating the line to see if all but the last endl; makes it through.

This could be a buffer flushing issue that the thread gave up control before it flushed the endl out.
 
The moral of the story is don’t be doing simple programs. :-)
 
Dr Transport said:
to end the line and add a newline, it didn't work, but if I typed in
You can do that? - output a bunch of "..." without the quotes??
 
256bits said:
You can do that? - output a bunch of "..." without the quotes??
I think he was just making a shortcut, with ... representing some delimited string.
 
  • Like
Likes   Reactions: jedishrfu
jedishrfu said:
This could be a buffer flushing issue that the thread gave up control before it flushed the endl out.
I was thinking this when I wrote my reply, but didn't mention it, about the thread giving up control prematurely.
 
  • Like
Likes   Reactions: jedishrfu
count << "\n" is likely significantly faster than count << std::endl; because the latter does cause a flush every time.
When printing to a scrolling window, a std::end takes about 0.5 ms on my system. (unless there was no output between endl's)
printing the numbers from 1 to 10000 takes 13 seconds with std::endl between the numbers, and only 8 seconds with "\n"
So don't use endl unless you want to flush (there are youtube movies about this).
 
At this point in time I am not worried about speed but wondering why endl; isn't working and flushing the buffer on some of these systems is a good thing.

As for giving the thread giving up the control, this was a count statement in the main function, not in the spawned thread, which hadn't been called yet.
 
  • #10
Buffers are usually flushed when full or when a file is closed or forced to explicitly. I don’t think endl will force it explicitly.
 
  • #11
From what find yesterday, endl; is defined as a \n followed by std::flush, so the flush is inherent in the function call...

I even tried to add a flush; for grins and the carriage return still didn't happen.
 
  • #12
So you're saying if you do a \n and flush explicitly, it works, but if you use an endl, which is defined as \n and flush it doesn't?
 
  • #13
To be clear a line feed aka \n and cr aka \r are not the same. On windows lines end in crlf whereas on unix variants it’s just \n

You implementation may in fact not flush on endl but it’s not a problem usually because eventually the buffer does get flushed.
 
  • #14
Vanadium 50 said:
So you're saying if you do a \n and flush explicitly, it works, but if you use an endl, which is defined as \n and flush it doesn't?
I didn't do a \n then a flush. I did do an endl; then tried a flush and there was no carriage return. The \n alone did result in a carriage return. Monday I'll try a few more things.
 
  • #15
@Dr Transport , I don't see that you have answered @256bits question:
256bits said:
You can do that? - output a bunch of "..." without the quotes??
Should we take your post literally with the ... and no quotes? If so, then I think the print statement is not valid.
 
  • #16
256bits said:
You can do that? - output a bunch of "..." without the quotes??

FactChecker said:
@Dr Transport , I don't see that you have answered @256bits question:

Should we take your post literally with the ... and no quotes? If so, then I think the print statement is not valid.

I think that these prior threads answers the question... no quotes necessary...
 
  • #17
FactChecker said:
@Dr Transport , I don't see that you have answered @256bits question:

Should we take your post literally with the ... and no quotes? If so, then I think the print statement is not valid.
It didn't need answering, @Mark44 seemed to be the only one who interpreted my post without reading too much into it. And no one has responded with a viable reason to the OP... Frankly I didn't think I needed to be so explicit and I figured the readers of this forum would be able to interpret a shorthand notation.
 
  • #18
Dr Transport said:
And no one has responded with a viable reason to the OP
I think our responses about buffers not getting flushed prior to a thread context switch is a likely reason.
Dr Transport said:
Frankly I didn't think I needed to be so explicit and I figured the readers of this forum would be able to interpret a shorthand notation.
I agree.
 
  • #19
Mark44 said:
I think our responses about buffers not getting flushed prior to a thread context switch is a likely reason.

Dr Transport said:
Frankly I didn't think I needed to be so explicit and I figured the readers of this forum would be able to interpret a shorthand notation.

I agree.

I agree with that, but it still does not explain why no carriage return isn't occurring, I wasn't able to recreate the same issue on another machine I have access to, the endl; resulted in a carriage return/newline whereas on the original machine I was working on it did not.

when I looked for further documentation online about the standard, endl; was explained as a carriage return followed by a flush().

As for the interpretation of what someone writes, I am at a loss, pretty much every thread on this forum takes a fair amount of interpretation to interpret someones thoughts and I have seen many threads which haven't been able to be deciphered.
 
  • #20
Dr Transport said:
It didn't need answering, @Mark44 seemed to be the only one who interpreted my post without reading too much into it. And no one has responded with a viable reason to the OP... Frankly I didn't think I needed to be so explicit and I figured the readers of this forum would be able to interpret a shorthand notation.
When faced with a computer code, computers take things very literally, and so should computer programmers. Pleas don't make us guess about your bugs. It's much less effort on your part to answer the question than it is on our part to guess what you really meant.

In any case, you should really consider that the ... might be hiding a bug.
 
  • #21
Do you print anything after the std::endl that you do see? If so, then the output buffer has been flushed. If you do print more and do not see it, then it may not have flushed the buffer.
 
  • #22
FactChecker said:
In any case, you should really consider that the ... might be hiding a bug.
The line with the ellipsis, ..., wasn't meant to be taken literally. I surmised that in post #6, and Dr Transport confirmed it in post #17.
 
  • #23
Mark44 said:
The line with the ellipsis, ..., wasn't meant to be taken literally. I surmised that in post #6, and Dr Transport confirmed it in post #17.
I think that @FactChecker understands this. When he says
FactChecker said:
In any case, you should really consider that the ... might be hiding a bug.
he means that the omitted code might contain something that is related to the problem observed. I think we've all seen it often at PF: the bug is not always where people think it is.
 
  • Like
Likes   Reactions: FactChecker
  • #24
DrClaude said:
I think that @FactChecker understands this. When he says

he means that the omitted code might contain something that is related to the problem observed. I think we've all seen it often at PF: the bug is not always where people think it is.
I understand, but in this case, what was omitted was not germain to the issue brought up "..." was meant to replace any random textual output that contained no other control characters... and anything printed out to the screen after is on the same line and no new line feed is seen until I manually insert a "\n".
 
  • #25
Dr Transport said:
I understand, but in this case, what was omitted was not germain to the issue brought up "..." was meant to replace any random textual output that contained no other control characters... and anything printed out to the screen after is on the same line and no new line feed is seen until I manually insert a "\n".
You may think that the surrounding code is not germane, but that assumption is often wrong. A better approach for debugging is to test a simple, minimal example. If the unexpected behavior is still there then you can show us more precisely what your code is. If the problem disappears, that is a definite clue. When issues with a flushed buffer are a factor, you need to know how much was or was not printed before and after the newline. Your test case should include prints before and after the missing part.

PS. One thing about your first post that confused me was that one case did not have ... in quotes but the second case did, as though it should be taken literally.
 
Last edited:
  • #26
I have provided all the information I will provide. My quote unquote in the second case quoted the first and was not meant to be confusing.

I provided all that was germane to the problem, I'm sorry you were unable to read what I wrote and help in any way..., again, the ... was meant as a place holder, nothing more, nothing less and in my last post it meant to replace un-formatted text without any control characters, case closed.
 
  • #27
Dr Transport said:
It didn't need answering, @Mark44 seemed to be the only one who interpreted my post without reading too much into it. And no one has responded with a viable reason to the OP... Frankly I didn't think I needed to be so explicit and I figured the readers of this forum would be able to interpret a shorthand notation.
Yes . I was kind of loose with my fingers, ( and of course brain but I can't admit that :oops: ).
 
  • #28
Since you tried it on another machine and the problem didn't show up, it could be
  • a compiler bug
  • some other part of the program rewriting memory it is not supposed to
Try changing the compiler options to see what happens (in particular optimization level). Also, check if the compiler versions are the same on the computers with and without the bug.
 
  • #29
DrClaude said:
Since you tried it on another machine and the problem didn't show up, it could be
  • a compiler bug
  • some other part of the program rewriting memory it is not supposed to
Try changing the compiler options to see what happens (in particular optimization level). Also, check if the compiler versions are the same on the computers with and without the bug.

I suspect it is a compiler bug, the work computer I was on is running an older version of Debian (my group doesn't update OS's or computers until they absolutely have to and frankly the guy who took it upon himself to keep things running is so OCD that any little change to his routine causes him to start at step one, so when it is running he won't change anything). The version of Debian I didn't see it was the latest version, so I think they fixed it.

Thanks
 

Similar threads

  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 23 ·
Replies
23
Views
3K
  • · Replies 1 ·
Replies
1
Views
2K
Replies
6
Views
2K
  • · Replies 3 ·
Replies
3
Views
3K
  • · Replies 2 ·
Replies
2
Views
9K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 9 ·
Replies
9
Views
4K
  • · Replies 2 ·
Replies
2
Views
3K