【问题标题】:Redirecting stdout/stderr on Windows在 Windows 上重定向 stdout/stderr
【发布时间】:2015-09-02 16:20:44
【问题描述】:

我有一个 Windows GUI 应用程序,它使用将调试/错误信息打印到 stdout/stderr 的第三方库。我找到了许多将它们重定向到我的日志文件的解决方案。但只有四分之五的工作符合预期。我在 WinXP SP3 32 位上使用 VS 2008 SP1。我没有包括错误处理,但没有调用返回错误。

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

在我测试它们之后(当然是单独测试),我得到了以下结果:
3 测试打印到 cout!
3 测试打印到 cerr!
4 测试 printf 到 cout!
4 测试打印到 cout!
4 测试 printf 到 cerr!
4 测试打印到 cerr!

为什么只有最后一个解决方案才能完全发挥作用?使用它安全吗?

更新。 XCode 测试结果:
2 测试 printf 到 cout!
2 测试打印到 cout!
2 测试 printf 到 cerr!
2 测试打印到 cerr!
4 测试 printf 到 cout!
4 测试打印到 cout!
4 测试 printf 到 cerr!
4 测试打印到 cerr!
第一个显然只是 Windows,第三个失败是因为没有采用 FILE* 参数的文件流构造函数。

【问题讨论】:

  • 我怀疑:第一个设置标准输出/错误句柄,但是在标准库已经使用旧的设置标准输出/标准错误之后。第二个可能不起作用,因为 Windows 不使用文件描述符。第三个仅适用于 cout/cerr,因为您实际上并没有对 stdout/stderr 做任何事情。最后一个是丑陋的非便携式黑客。
  • @immibis 解决方案是......?稍后将在 OSX 上测试其中的 3 个。
  • 我没有解决方案,这是我没有将其作为答案的一部分发布的原因之一。
  • @immibis 为什么你称最后一个丑陋的非便携式黑客?丑陋见仁见智,我对非便携式部分更感兴趣。
  • @Shark 第四个正是stdout和stderr的重定向。如果不保存原始指针,原始指针永远不会关闭或恢复(无耻plug),但它们会被重定向。

标签: c++ c windows stdout stderr


【解决方案1】:

从头到尾:

  1. 您正在将实际的 FILE pointer 更改为 stdout 和 stderr。很明显为什么它有效。 std::cout 和 std::cerr 最终将输出发送到这些指针。

  1. std::ios.rdbuf 更改 std::ios 实例(在本例中为 std::cout 和 std::cerr)发送它的流的

  1. 我从未听说过。我可能会做一些研究并编辑答案。

  1. 同 2。

【讨论】:

  • Markdown 将您的数字重新格式化为 4/5/6/7 而不是 4/3/2/1。
  • 我猜你的意思是 4-3-2-1 :) 好吧,我查看了标准输出的定义,它看起来像这样 #define stdout (&amp;__iob_func()[1]),所以我不确定第四个解决方案有多安全。
  • @Sergi0 这只是一个包含描述符(FILE 指针)的数组。
猜你喜欢
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
  • 1970-01-01
相关资源
最近更新 更多