我有 Xubuntu 14.04的g ++版本4.8.4编译器。在我的OpenCV代码(用Eclipse CDT编写)中,我连续写了以下三行:
/* Some codes here*/
cerr << "No match found. # of false positives: " << falsePositives << endl;
cout << "Press a key to continue..." << endl;
waitKey(0);
以下是结果:
Press a key to continue...
No match found. # of false positives: 1
/*there is a blank line*/
为什么这两行的顺序在执行时发生了变化?在前面的行中根本没有并行代码,但它们看起来像并行(同时)。
我知道cerr没有缓冲,而cout是缓冲的(这意味着,afai,cerr比cout慢);但是,无论如何,不应该改变执行的顺序?那个空白行从哪里来? (可能来自其中一个但是哪一个?)
有人可以解释这两行的内容吗?
非常感谢你。
修改: 我没有使用ubuntu,我使用 Xubuntu 14.04。抱歉这个错误,我的思绪太乱了,但我认为这不会影响结果。 我使用Eclipse提供的控制台来显示它们。我试图将std ::前缀附加到所有cout,cerr,endl。结果是一样的。
有趣的是,当我刚写了一个新文件时,包括:
#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;
}
我使用xfce4-terminal和g ++编译器获得了预期的输出(第一个cerr然后是cout)。
使用Eclipse CDT时出现问题。我还想提醒大家,我在OpenCV上工作。
Chris Dodd的第四个建议:
&#34;您的代码实际上不是您上面发布的内容,而且差异虽然看似不重要,但实际上至关重要。&#34;
当然,我的代码确实包含的不是我输入的内容,但有很多,我的意思是在这些行之前有很多计算等。但是,可能存在相关部分,在此之前我无法实现。另外,我没有将stdout和/或stderr重定向到这些行之前的不同设备/文件/管道。
编辑2: 当我在Eclipse CDT的Debug模式下执行程序时,按照装配线
在cerr
行之后执行以下操作(当然还有其他汇编代码):
callq 0x403500 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
callq 0x403470 <_ZNSolsEi@plt>
callq 0x403770 <_ZNSolsEPFRSoS_E@plt>
在cout
行之后执行以下操作(当然还有其他汇编代码):
callq 0x403500 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
callq 0x403770 <_ZNSolsEPFRSoS_E@plt>
callq 0x403670 <_ZN2cv7waitKeyEi@plt>
并且它们都给出了相同的错误消息:
&#34; std :: basic_ostream&gt;&amp;的std ::运营商LT;&LT; &gt;(std :: basic_ostream&gt;&amp;,char const *)@ plt at 0x403500&#34;
并且该过程继续使用其他行的汇编代码而不会终止。
PS:当我注释掉这两行时,它按预期工作。因此,我的结论是,在这些行之前可能存在相关的代码部分,但我无法弄清楚它们。
答案 0 :(得分:6)
std::cerr
和std::cout
是不同的流,它们不同步。
所以你真的无法假设如何显示两者的输出。在这种情况下,输出恰好在错误之前显示。
您可以依赖 中的订单
。此外,std::cout
被缓冲而std::cerr
不被缓存,这通常会导致此类问题,但由于您使用std::endl
(刷新流)这不会真的适用于你的情况。
答案 1 :(得分:2)
这两行的顺序没有改变。但是,无论生成输出的代码是什么,您都看不到保存输出发送到两个流的顺序。它可能只是等待然后读取两个流以产生最终输出。如果不知道你的环境是什么样子,很难确定。
答案 2 :(得分:1)
好吧,std::endl
将流刷新到底层设备,这意味着输出不能合法地成为您描述的内容 - 第一个endl
在输出之前排序到cout
,所以必须刷新cerr
流,并在执行第二行之前在终端上显示输出。
这意味着有很多可能性
endl
定义为除std::endl
以外的其他内容,并且它不会刷新(如果您尝试进行模糊处理,则可能)因此,如果您想要真正回答这个问题,您需要发布并MVCE展示您实际在做什么。
答案 3 :(得分:1)
Eclipse CDT在创建进程期间将自身插入cerr
和cout
流。它可以将cerr
流回显到其中一个窗口,然后写入预期的控制台。各种各样的发球台。
由于它正在轮询这些流,因此无法同步它们。这可以解释这种行为。