Reputation: 147
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
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
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
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
endl
to be something other than std::endl
, and it doesn't flush (possible if you're trying to be obfuscated)So if you want a real answer to this question, you need to post and MVCE demonstrating what you are actually doing.
Upvotes: 0
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