代码之家  ›  专栏  ›  技术社区  ›  SPWorley

限制cout流?

  •  4
  • SPWorley  · 技术社区  · 15 年前

    一个迷题击中了我。在一些简单的测试代码中,如果我将太多字符流式传输到标准输出,程序就会失败。奇怪但很容易复制。这可能是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);
    }
    

    前面的代码只是从stdin加载一个字符流,并以相反的顺序输出它们。它最多可以处理100K左右的字符,但对于较大的文件,在Windows中会出现“写入标准输出时出错”消息。它总是和同一个角色一起死去。 您只需使用类似“cat bigfile.txt | reverse.exe”的shell命令即可重现该问题。MSFT和英特尔编译器的工作原理类似。

    我意识到stdout上可能有一个缓冲区,但它是否应该在被填满时自动刷新?

    6 回复  |  直到 15 年前
        1
  •  4
  •   yves Baumes    15 年前

    您可以尝试通过以下方式强制缓冲区刷新其内容:

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

    否则 std::endl 也可以工作,但也提供了一条线和一条线的末端(我想你不想这样吧?)

        2
  •  1
  •   Sinan Ünür    15 年前

    这里没有这样的问题:

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

    编辑:

    我通过编译你发布的程序来测试这一点。我创建了一个由0123456789重复100000次组成的文件(使其大小为1000000字节)。然后,我跑了

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

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

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

        3
  •  1
  •   Sliq    15 年前

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

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

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

        4
  •  0
  •   Robert Harvey    15 年前

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

    我不知道C++中的命令是什么,但是在C语言中是这样的。

    System.Threading.Sleep(10);
    
        5
  •  0
  •   SPWorley    15 年前

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

        6
  •  0
  •   Billy ONeal IS4    15 年前