Ограничить поток cout? - PullRequest
4 голосов
/ 23 мая 2009

Головоломка, которая ударила меня. В некотором простом тестовом коде, если я передаю слишком много символов в stdout, программа завершается неудачно. Странно, но очень воспроизводимо. Это может быть проблема только для 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);
}

Предыдущий код просто загружает поток символов из стандартного ввода и выводит их в обратном порядке. Он отлично работает до 100 КБ или около того символов, но умирает с сообщением «Ошибка записи стандартного вывода» в Windows для файлов большего размера. Он всегда умирает с одним и тем же персонажем. Команда оболочки типа "cat bigfile.txt | reverse.exe" - это все, что вам нужно, чтобы воспроизвести проблему. И компиляторы MSFT и Intel действуют одинаково.

Я понимаю, что на stdout может быть буфер, но не должен ли он автоматически очищаться при заполнении?

Ответы [ 6 ]

4 голосов
/ 23 мая 2009

Вы можете попытаться принудительно сбросить содержимое буфера следующим образом:

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

В противном случае std::endl также работает, но обеспечивает и конец строки (что, я полагаю, не нужно?)

1 голос
/ 24 мая 2009

Возможно, проблема будет в трубе оператора (|), а не в "кошке". Интерпретатор команд Windows [1] не имеет реальных каналов (например, Unix) и имитирует их, используя временные файлы. Возможно, вам не хватает места на диске или переполнение буфера в интерпретаторе команд.

Вы можете попробовать набрать bigfile.txt | reverse.exe и посмотреть, получите ли вы те же результаты.

[1] По крайней мере в старых версиях не было настоящих каналов. Я не смотрел на последних версиях. Интересно, что Майкл Барр не смог воспроизвести его на Vista x64. Возможно, MS исправила проблему.

1 голос
/ 23 мая 2009

Здесь такой проблемы нет:

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 символов заняло довольно много времени.

0 голосов
/ 23 мая 2009

Эта проблема возникала у меня раньше, если вы пытались написать специальный символ в стандартный вывод на win32. Есть ли такие символы в ваших тестовых данных?

0 голосов
/ 23 мая 2009

Спасибо за все предложения, особенно Майклу Берру, который правильно предположил, что команда cat, а не reverse.exe, может не работать! Это именно то, что было .. reverse.exe

0 голосов
/ 23 мая 2009

Можете ли вы спать в течение короткого периода времени во время каждой итерации цикла, или, возможно, каждые 100 итераций? Это даст ОС возможность очистить буфер.

Я не знаю, какая команда для этого есть в c ++, но в c # это

System.Threading.Sleep(10);
...