Redirecting stdout / stderr on Windows
I have a Windows GUI application that uses third party libraries that print debug / error information to stdout / stderr. I have found many solutions to redirect them to a log file. But only 1.5 out of 4 work as expected. I am using VS 2008 SP1 on WinXP SP3 32-bit. I did not enable error handling, but no calls returned any errors.
// First one:
SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)_get_osfhandle(_fileno(log_file.get_FILE())));
SetStdHandle(STD_ERROR_HANDLE, (HANDLE)_get_osfhandle(_fileno(log_file.get_FILE())));
printf("%s", "1 Test printf to cout!\n");
fprintf(stderr, "%s", "1 Test printf to cerr!\n");
std::cout << "1 Test print to cout!\n";
std::cerr << "1 Test print to cerr!\n";
fflush(stdout);
fflush(stderr);
// Second one:
_dup2(_fileno(log_file.get_FILE()), _fileno(stdout));
_dup2(_fileno(log_file.get_FILE()), _fileno(stderr));
printf("%s", "2 Test printf to cout!\n");
fprintf(stderr, "%s", "2 Test printf to cerr!\n");
std::cout << "2 Test print to cout!\n";
std::cerr << "2 Test print to cerr!\n";
fflush(stdout);
fflush(stderr);
// Third one:
std::ofstream out_stream(log_file.get_FILE());
std::cout.rdbuf(out_stream.rdbuf());
std::cerr.rdbuf(out_stream.rdbuf());
printf("%s", "3 Test printf to cout!\n");
fprintf(stderr, "%s", "3 Test printf to cerr!\n");
std::cout << "3 Test print to cout!\n";
std::cerr << "3 Test print to cerr!\n";
fflush(stdout);
fflush(stderr);
// Fourth one:
*stdout = *log_file.get_FILE();
*stderr = *log_file.get_FILE();
printf("%s", "4 Test printf to cout!\n");
fprintf(stderr, "%s", "4 Test printf to cerr!\n");
std::cout << "4 Test print to cout!\n";
std::cerr << "4 Test print to cerr!\n";
fflush(stdout);
fflush(stderr);
After I tested them (separately of course), I got the following results:
3 Test print in cout!
3 Test print in cerr!
4 Test printf on cout!
4 Test print in cout!
4 Checking print on cerr!
4 Test print in cerr!
Why only the last solution works completely? Is it safe to use?
Update. Xcode test results:
2 printf test on cout!
2 Test print in cout!
2 Test printf on cerr!
2 Test print in cerr!
4 Test printf on cout!
4 Test print in cout!
4 Checking print on cerr!
4 Test print in cerr!
The first one is obviously Windows-only, while the third is due to the lack of a file stream constructor that takes a FILE * parameter.
source to share
From the end:
- You are changing the actual
FILE
pointer to stdout and stderr. It's obvious why this works. std :: cout and std :: cerr end up sending the output to these pointers.
- std :: ios.rdbuf changes the stream where the std :: ios instance (in this case std :: cout and std :: cerr) send the stream.
- I've never heard of this. I can research a bit and edit the answer.
- Same as 2.
source to share