提问者:小点点

为什么在打印某些东西时不保留顺序,先用cerr,然后用COUT?


我有一个带有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被缓冲(这意味着,afaik,cerr比cout慢);但是,不管怎么样,难道不应该改变执行顺序吗?那空行是从哪里来的?(可能是从其中一个端部,但是哪一个端部?)

有人能解释一下那两行是怎么回事吗?

太谢谢你了。

我不使用ubuntu,我使用14.04。对不起,我的脑子太乱了,但我想这不会影响结果。我使用Eclipse's提供的控制台来显示它们。我试图将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的。

克里斯·多德的第四个建议:

当然,我的代码确实包含了我键入的内容以外的内容,但是在这些行之前有很多,我的意思是很多计算等等。然而,可能有一些相关的部分,在此之前我无法意识到。而且,我根本没有在这些行之前将stdout和/或stderr重定向到不同的设备/文件/管道。

编辑2:当我在Eclipse CDT的调试模式下按照流水线执行程序时,

行之后,将执行以下代码(当然还有其他汇编代码):

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

行之后,执行以下代码(当然还有其他汇编代码):

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

它们都给出了相同的错误消息:

“std::basic_ostream>&;std::operator<<>(Std::basic_ostream>&;,char const*)@plt,地址0x403500”没有可用的源

并且该过程继续使用其他行的程序集代码而不终止。

PS:当我注释掉除了那两行之外的所有内容时,它就像预期的那样工作了。因此,我的结论是,在这些行之前可能有相关的代码部分,但我不能把它们弄清楚。


共3个答案

匿名用户

是不同的流,它们不同步。因此,您不能假设两者的输出是如何显示的。在这种情况下,输出恰好显示在错误之前。

您可以依赖于任何一个流中的顺序。

此外,是缓冲的,而不是,这通常会导致这种问题,但是因为您使用的是(它会刷新流),所以这并不适用于您的情况。

匿名用户

这两行的顺序没有改变。但是,无论生成您所看到的输出的代码是什么,都无法保留输出发送到两个流的顺序。它可能只是等待,然后读取两个流以产生最终输出。如果不知道你的环境是什么样子,就很难确定。

匿名用户

嗯,将流刷新到底层设备,这意味着输出在法律上不可能是您所描述的--第一个在输出到之前被排序,因此流必须被刷新,并且输出在执行第二行之前出现在终端上。

这意味着有很多可能性

  • 您已将定义为以外的内容,并且它不会刷新(如果您试图被混淆,则可能)/li>

所以如果你想要这个问题的真实答案,你需要post和MVCE演示你实际在做什么。