Как freopen () и stdout и stderr в один выходной файл под Windows - PullRequest
0 голосов
/ 15 мая 2018

У меня есть приложение для Windows Win32 / GUI, которое иногда выводит интересные выходные данные как на stdout, так и на stderr, поэтому я хотел бы записать этот вывод в файл для просмотра после выхода из приложения.

Проблема в том, что я могу успешно вызвать freopen_s() для захвата stdout вывода в файл, или Я могу использовать его для захвата stderr вывода в файл, нопопытка сделать оба сразу приводит к усеченному файлу с поддельными данными.

Ниже приведена простая программа, которая воспроизводит проблему;если я закомментирую один из двух вызовов freopen_s(), то получу ожидаемый результат в создаваемом файле blah.txt (т.е. в одной из двух текстовых строк), но мне хотелось бы получитьblah.txt, содержащий обе строки текста.

Возможно ли это в Windows?Я мог бы вернуться к созданию двух разных файлов (например, blah_stdout.txt и blah_stderr.txt), но я бы предпочел не делать этого, поскольку в этом случае мне пришлось бы вручную восстанавливать относительный порядок, в котором генерировались выходные данные stdout и stderr.

int main(int argc, char *argv[])
{
   const char * outFileName = "blah.txt";
   FILE * junk1 = NULL, junk2 = NULL;
   if (freopen_s(&junk1, outFileName, "w", stdout) != 0) abort();
   if (freopen_s(&junk2, outFileName , "w", stderr) != 0) abort();
   printf("This text was printed to stdout and should appear in blah.txt\n");
   fprintf(stderr, "This text was printed to stderr and should appear in blah.txt\n");
   return 0;
}

1 Ответ

0 голосов
/ 15 мая 2018

Режим открытия "w" задокументирован как

Открывает пустой файл для записи.Если данный файл существует, его содержимое уничтожается.

, но даже "w +" и "a" завершаются ошибкой.

Если вы используете CRT с dup2, вы можете сделать это:

#include <io.h> // MS CRT

...

FILE * junk1 = NULL;
if (freopen_s(&junk1, outFileName, "w", stdout) != 0) abort();
_dup2(1, 2); // Assign stderr to same file as stdout

Этот код записывал обе строки в файл, когда я тестировал его, но из комментариев видно, что это не всегда так.Более старые версии Visual Studio с большей вероятностью будут работать.

Если вы хотите выбросить всю переносимость, вы также можете получить доступ к структуре за объектами FILE (struct _iobuf) напрямую (_iob /__iob_func) и перезаписать элементы значениями из другого ФАЙЛА.Это невозможно в VS 2015 и более поздних версиях :

Инкапсуляция FILE: В предыдущих версиях тип FILE был полностью определен вТаким образом, пользовательский код мог проникнуть в ФАЙЛ и смешаться с его внутренностями.Мы реорганизовали библиотеку stdio для улучшения инкапсуляции деталей реализации библиотеки.Как часть этого, FILE, как определено в, теперь является непрозрачным типом, и его члены недоступны снаружи самой CRT.

...