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);
}

前のコードは、stdin から char のストリームをロードし、それらを逆の順序で出力するだけです。100K 程度の文字までは問題なく動作しますが、それより大きいファイルの場合、Windows で「stdout の書き込みエラー」メッセージが表示されて停止します。いつも同じキャラで死ぬ。問題を再現するために必要なのは、「cat bigfile.txt | reverse.exe」のようなシェル コマンドだけです。MSFT コンパイラと Intel コンパイラはどちらも同様に動作します。

stdout にバッファがある可能性があることは認識していますが、いっぱいになったときに自動的にフラッシュされるべきではありませんか?

4

6 に答える 6

1

問題はおそらく "cat" ではなくパイプ演算子 (|) です。Windows コマンド インタープリタ [1] には (Unix のような) 実際のパイプはなく、一時ファイルを使用してそれらをシミュレートします。ディスク容量が不足しているか、コマンド インタープリターの一部のバッファーがオーバーフローしている可能性があります。

「type bigfile.txt | reverse.exe」を試して、同じ結果が得られるかどうかを確認できます。

[1] 少なくとも古いバージョンには実際のパイプがありませんでした。最新版は見ていません。興味深いのは、Michael Burr が Vista x64 でそれを再現できなかったことです。多分MSは問題を修正しました。

于 2009-05-24T08:42:45.603 に答える
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 に答える
0

すべての提案に感謝します。特に、reverse.exe ではなく cat コマンドが失敗する可能性があることを正しく理論化した Michael Burr に感謝します! まさにその通りでした.. reverse.exe < bigfile.txt は正常に動作しますが、 cat bigfile.txt | reverse.exe が「stdout の書き込みエラー」で失敗します。CAT が失敗する理由も謎ですが、少なくともコードに関連するものではありません。

于 2009-05-23T00:55:27.200 に答える
0

ループの反復ごと、あるいは 100 回の反復ごとに短時間スリープできますか? これにより、OS がバッファをフラッシュする機会が与えられます。

これを行うためのコマンドがC ++で何であるかはわかりませんが、C#では

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

win32 の stdout に特殊文字を書き込もうとすると、以前にこの問題が発生しました。テストデータにそのような文字はありますか?

于 2009-05-23T16:52:07.820 に答える