Aka
Aka

Reputation: 147

Why the order is not preserved when printing something, first with cerr and then cout?

I have g++ version 4.8.4 compiler with Xubuntu 14.04. In the midst of my OpenCV code (written in Eclipse CDT), I wrote the following three lines consecutively:

/* Some codes here*/
cerr << "No match found. # of false positives: " << falsePositives << endl;
cout << "Press a key to continue..." << endl;
waitKey(0);

and here is the result:

Press a key to continue...
No match found. # of false positives: 1
/*there is a blank line*/

Why the order of those two lines changed at the execution time? There is no parallel code at all in the previous lines but they seems to work like parallel (at the same time).

I know that cerr is not buffered whereas cout is buffered (which means, afaik, cerr is slower compared to cout); however, no matter what, shouldn't the order of execution be changed? And where does that blank line comes from? (probably from one of those endls but which one?)

Can someone explain what is going on those two lines?

Thank you so much.

EDIT: I don't use ubuntu, I use Xubuntu 14.04. Sorry for that mistake, my mind was too messy but I think it does not effect the result. I use Eclipse's provided console to display them. I tried to append std:: prefix to all cout, cerr, endl. The result is same.

The interesting point is that when I just wrote a new file including:

#include <iostream>
#include <cstdlib>
int main()
{       
    std::cerr << "No match found. # of false positives: " << 2 << std::endl;
    std::cout << "Press a key to continue..." << std::endl;

    return 0;
}

I got the expected output(first cerr and then cout) by using xfce4-terminal and g++ compiler.

The problem occurs when using Eclipse CDT. I also want to remind all of you that I work on OpenCV.

Chris Dodd's 4th suggestion:

"your code is actually something other than what you've posted above, and the difference, while seemingly unimportant, is actually crucial."

Of course my code does contain other than what I typed but there are lots of, I mean lots of computation etc. before those lines. However, there might be relating parts before which I could not realise. Also, I didn't redirected stdout and/or stderr to different devices/files/pipes before those lines at all.

EDIT 2: When I execute the program in the Debug mode of Eclipse CDT, following assembly lines,

After cerr line the followings are executed (as well as other assembly codes of course):

callq 0x403500 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
callq 0x403470 <_ZNSolsEi@plt>
callq 0x403770 <_ZNSolsEPFRSoS_E@plt>

After cout line the followings are executed (as well as other assembly codes of course):

callq 0x403500 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
callq 0x403770 <_ZNSolsEPFRSoS_E@plt>
callq 0x403670 <_ZN2cv7waitKeyEi@plt>

and they all give the same error message:

No source available for "std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*)@plt at 0x403500"

and the process continues with other lines of assembly code without termination.

PS: When I commented out everthing but those two lines, it works as expected. Thus, my conclusion is that, there may be relevant code part before those lines but I couldn't figure them out.

Upvotes: 7

Views: 2385

Answers (4)

Jesper Juhl
Jesper Juhl

Reputation: 31459

std::cerr and std::cout are different streams and they are not synchronized. So you really can't assume anything about how output to both gets shown. In this case, the output happens to be shown before the error.

You can rely on the order within either stream.

Additionally, std::cout is buffered and std::cerr is not, and that often causes this kind of problem, but because you are using std::endl (which flushes the stream) this doesn't really apply in your case.

Upvotes: 8

David Thomas
David Thomas

Reputation: 798

Eclipse CDT is inserting itself into the cerr and cout streams during the creation of your process. It may echo the cerr stream to one of its windows and then write to the intended console. A tee of sorts.

Since it is polling these streams, it is not be possible to synchronize them. This could explain the behavior.

Upvotes: 1

Chris Dodd
Chris Dodd

Reputation: 126358

Well, std::endl flushes the stream to the underlying device, which mean that the output cannot legally be what you describe -- the first endl is sequenced before the output to cout, so the cerr stream must be flushed and the output appear on the terminal before the second line is executed.

Which means there are a number of possibilities

  • your computer is broken or compiler is buggy (unlikely)
  • you've defined endl to be something other than std::endl, and it doesn't flush (possible if you're trying to be obfuscated)
  • you've redirected stdout and/or stderr to different devices/files/pipes and are later combining them, and that later combination step is reordering things.
  • your code is actually something other than what you've posted above, and the difference, while seemingly unimportant, is actually crucial.

So if you want a real answer to this question, you need to post and MVCE demonstrating what you are actually doing.

Upvotes: 0

David Schwartz
David Schwartz

Reputation: 182819

The order of those two lines was not changed. However, whatever code produced the output you saw failed to preserve the order in which the output was sent to the two streams. It's possible that it just waited and then read both streams to produce the final output. It's hard to be sure without knowing what your environment looks like.

Upvotes: 2

Related Questions