4

一个困扰我的谜题。在一些简单的测试工具代码中,如果我将太多字符流式传输到标准输出,程序就会失败。奇怪但非常可重复。这可能是 Windows 唯一的问题,但很容易看出:

#include <iostream>
#include <deque>

using namespace std;

int main() 
{
  deque<char> d;
  char c;

  while (cin.get(c)) d.push_back(c);

  for (deque<char>::reverse_iterator j = d.rbegin(); j != d.rend(); j++)
    cout << (*j);
}

前面的代码只是从标准输入加载一个字符流并以相反的顺序输出它们。它适用于最多 100K 左右的字符,但对于较大的文件,在 Windows 中会因“错误写入标准输出”消息而死。它总是以相同的角色死去。像“cat bigfile.txt | reverse.exe”这样的 shell 命令就是重现问题所需要的。MSFT 和 Intel 编译器的行为都类似。

我意识到标准输出上可能有一个缓冲区,但是当它被填充时不应该自动刷新吗?

4

6 回答 6

4

您可以尝试强制缓冲区以这种方式刷新其内容:

cout << (*j) << std::flush;

否则std::endl也可以,但也提供和行尾(我想你不想要吗?)

于 2009-05-22T23:15:32.253 回答
1

这里没有这样的问题:

C:\Temp> cl
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86

编辑:更多信息

我通过编译您发布的程序对此进行了测试。我创建了一个包含 0123456789 的文件,重复了 100,000 次(使其大小为 1,000,000 字节)。然后,我跑了

C:\Temp> t.exe < test.in

C:\Temp> cat test.in | t.exe

C:\Temp> t.exe < test.in > test.out

没有问题。等待 1,000,000 个字符滚动确实需要相当长的时间。

于 2009-05-22T22:56:39.500 回答
1

问题可能是管道运算符(|)而不是“cat”。Windows 命令解释器[1] 没有真正的管道(如 Unix)并使用临时文件模拟它们。您可能会用完磁盘空间或溢出命令解释器中的某些缓冲区。

您可以尝试“键入 bigfile.txt | reverse.exe”,看看是否得到相同的结果。

[1] 至少旧版本没有真正的管道。我没看过最新版本。有趣的是,Michael Burr 无法在 Vista x64 上重现它。也许MS已经解决了这个问题。

于 2009-05-24T08:42:45.603 回答
0

您可以在每次循环迭代期间或每 100 次迭代期间睡一小段时间吗?这将使操作系统有机会刷新缓冲区。

我不知道在 c++ 中执行此操作的命令是什么,但在 c# 中它是

System.Threading.Sleep(10);
于 2009-05-22T22:57:48.983 回答
0

感谢所有的建议,尤其是迈克尔·伯尔,他正确地推测了 cat 命令而不是 reverse.exe 可能会失败!就是这样...... reverse.exe < bigfile.txt 工作正常,但 cat bigfile.txt | reverse.exe 因“写入标准输出错误”而失败。现在为什么 CAT 会失败也是一个谜,但至少现在它与代码无关。

于 2009-05-23T00:55:27.200 回答
0

如果您尝试在 win32 上向标准输出写入特殊字符,我之前就遇到过这个问题。您的测试数据中有这样的字符吗?

于 2009-05-23T16:52:07.820 回答