Перенаправление stdout и stderr одновременно
От: Nikita.Trophimov  
Дата: 03.04.13 08:41
Оценка:
Приветствую.

#include <cstdio>

int main()
{
    std::freopen("D:/output.txt", "w", stdout);
    std::setbuf(stdout, NULL);
    std::freopen("D:/output.txt", "w", stderr);

    std::printf("1 \n");
    std::fprintf(stderr, "2 \n");
    std::printf("3 \n");
}


В результате выполнения данного кода в output.txt оказывается

2
3


Если пробежаться в отладчике, то будет заметно, что до вывода второй строки в файле действительно присутствует первая, однако она перезаписывается сразу после записи второй (первая не появляется вообще, если убрать вызов функции std::setbuf или не сделать std::fflush — я так понимаю, что в Win stdout не имеет строковой буферизации).

Следующий код работает точно так же:

#include <fstream>
#include <iostream>

int main()
{
    std::ofstream std_out("output.txt");
    std::cout.rdbuf(std_out.rdbuf());

    std::ofstream std_err("output.txt");
    std::cerr.rdbuf(std_err.rdbuf());

    std::cout << "1" << std::endl;
    std::cerr << "2" << std::endl;
    std::cout << "3" << std::endl;
}


Почему так происходит? Ленивое создание файла?
Re: Перенаправление stdout и stderr одновременно
От: B0FEE664  
Дата: 03.04.13 09:27
Оценка: +1
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Почему так происходит? Ленивое создание файла?

Я не знаю, почему так получается, но думаю, что если один файл отрыть два раза, то позиция (offset) записи у хендлеров файлов не будет согласована. Сначала записали 1 со смещением 0, потом записали 2 со смещением 0, потом записали 3 со смещением 1, получилось 23. Как-то так.
И каждый день — без права на ошибку...
Re: Перенаправление stdout и stderr одновременно
От: watch-maker  
Дата: 03.04.13 10:43
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Почему так происходит?

На всякий случай, если тебя интересует не только почему это происходит, но и как это исправить^
Вместо открытия файла во второй раз, можно использовать копию файлового дескриптора.
dup2(fileno(stdout), fileno(stderr));
Ну и привести настройки буферизации stdout и stderr в согласованное состояние чтобы строчки между собой не перемешивались.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.