Why the order is not preserved when printing something, first with cerr and then cout?
我有Xubuntu 14.04的g ++版本4.8.4编译器。在我的OpenCV代码(用Eclipse CDT编写)中,我连续写了以下三行:
1 2 3 4 | /* Some codes here*/ cerr <<"No match found. # of false positives:" << falsePositives << endl; cout <<"Press a key to continue..." << endl; waitKey(0); |
这是结果:
1 2 3 | 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。结果是一样的。
有趣的是,当我刚写了一个新文件时,包括:
1 2 3 4 5 6 7 8 9 | #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上工作。
克里斯多德的第四个建议:
"你的代码实际上不是你上面发布的内容,而且差异虽然看似不重要,但实际上是至关重要的。"
当然,我的代码确实包含了我输入的内容以外的内容,但是有很多内容,我的意思是在这些行之前有很多计算等。但是,可能存在相关部分,在此之前我无法实现。此外,我没有将stdout和/或stderr重定向到这些行之前的不同设备/文件/管道。
编辑2:
当我在Eclipse CDT的Debug模式下执行程序时,按照装配线,
在
1 2 3 | callq 0x403500 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> callq 0x403470 <_ZNSolsEi@plt> callq 0x403770 <_ZNSolsEPFRSoS_E@plt> |
在
1 2 3 | callq 0x403500 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> callq 0x403770 <_ZNSolsEPFRSoS_E@plt> callq 0x403670 <_ZN2cv7waitKeyEi@plt> |
他们都给出了相同的错误信息:
没有可用于"std :: basic_ostream>&amp; std :: operator <<>(std :: basic_ostream>&amp;,char const *)@ plt at 0x403500"的源代码
并且该过程继续使用其他的汇编代码行而不终止。
PS:当我注释掉这两行时,它按预期工作。因此,我的结论是,在这些行之前可能存在相关的代码部分,但我无法弄清楚它们。
所以你真的无法假设如何显示两者的输出。在这种情况下,输出恰好在错误之前显示。
您可以依赖任一流中的订单。
另外,
这两行的顺序没有改变。但是,无论生成输出的代码是什么,您都看不到保存输出发送到两个流的顺序。它可能只是等待然后读取两个流以产生最终输出。如果不知道你的环境是什么样的话,很难
Eclipse CDT在创建进程期间将自身插入到
由于它正在轮询这些流,因此无法同步它们。这可以解释这种行为。
好吧,
这意味着有很多可能性
- 你的电脑坏了或编译器有问题(不太可能)
-
你已经将
endl 定义为std::endl 以外的东西,并且它不会刷新(如果你试图被混淆可能) - 你已经将stdout和/或stderr重定向到不同的设备/文件/管道,并且稍后将它们组合在一起,后来的组合步骤正在重新排序。
- 你的代码实际上不是你上面发布的代码,而差异虽然看似不重要,但实际上是至关重要的。
因此,如果您想要真正回答这个问题,您需要发布和MVCE演示您实际在做什么。