通过 freopen() 重定向后恢复标准输出 [英] Restoring stdout after redirecting it via freopen()

查看:98
本文介绍了通过 freopen() 重定向后恢复标准输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是如何捕获 printf 的输出? - 特别是 jxh 的回答.

This is a follow-up to How to capture output of printf? - specifically the answer by jxh.

我遇到了 Viesturs 在 2018 年遇到的答案中的代码问题.有人建议他打开一个新问题,他说他的帐户不允许,所以我打开了一个同样的新问题.

I am having the same trouble with the code in the answer that Viesturs was having in 2018. It was suggested to him that he open a new question, which he said his account didn't allow, so I'm opening a new question along the same lines.

在 2012 年的那个答案中,最初的提问者说它有效.Viesturs 在 2018 年表示,在代码运行后,控制台和重定向文件中都没有出现进一步的输出.

On that answer, in 2012, the original questioner said it worked. In 2018, Viesturs said after the code was ran, further output neither appeared on the console nor in the redirected file.

我遇到了同样的问题.使用下面的代码,this should not be redirected\n 不会显示在控制台上,也不会出现在重定向的文件中.重定向的文件只包含第一行打印.

I'm having the same problem. Using the code below, this shouldn't be redirected\n isn't shown on the console, and isn't in the redirected file. The redirected file only contains the first printed line.

我使用的是 gcc 8.3.0,也尝试了 gcc 6.5.0.glibc 2.29.

I'm using gcc 8.3.0, and also tried gcc 6.5.0. glibc 2.29.

请注意,我不想用 "CON" 之后 freopen .即使可行,我也想保留原始标准输出,因为它本身可能是重定向.(虽然在我的测试中,它只是控制台.)

Note that I do NOT want to freopen with "CON" afterward. Even if that works, I want to preserve the original stdout, since it could itself be a redirect. (Although in my testing, it's just been the console.)

或者:jxh 的答案有一个错误;我犯了和 Viesturs 一样的错误;或者(我最好的猜测)在 gcc 6.5.0 或 glibc 2.29 之前的某个时间引入(或修复)了一个错误.

Either: the jxh answer has a bug in it; I'm making the same mistake Viesturs was; or (my best guess) there was a bug introduced (or fixed) sometime earlier than gcc 6.5.0 or glibc 2.29.

redirected.c

#include <unistd.h>
#include <stdio.h>

void funcB() {
   printf("this should be redirected\n");
   fflush(stdout);
}

int main() {
   int stdout_fd = dup(STDOUT_FILENO);
   freopen("/tmp/redirected", "w", stdout);
   funcB();
   fclose(stdout);
   dup2(stdout_fd, STDOUT_FILENO);
   stdout = fdopen(STDOUT_FILENO, "w");
   close(stdout_fd);

   printf("this shouldn't be redirected\n");
   fflush(stdout); // shouldn't make a difference if this is here
}

输出:

$ gcc redirected.c
$ ./a.out
<THERE IS NO OUTPUT>
$ cat /tmp/redirected
this should be redirected

推荐答案

没有正确的解决方案可能涉及:

No correct solution to this can involve:

  • 分配给stdout,因为stdout 不是变量/左值.它是一个扩展为 FILE * 类型表达式的宏.如果它碰巧也是一个左值,那么这是它发生在任何特定实现上的实现细节,而不是语言的一部分.
  • fclose(stdout),因为在 fclose(stdout) 之后,在程序的任何地方进一步使用 stdout,隐式的(例如 printf) 或显式,在剩余的执行期间,调用未定义的行为.
  • assigning to stdout, because stdout is not a variable/lvalue. It's a macro that expands to an expression of type FILE *. If it happens to also be an lvalue, that's an implementation detail for whatever particular implementation it happens on, not part of the language.
  • fclose(stdout), because after fclose(stdout), any further use of stdout anywhere in the program, implicit (e.g. printf) or explicit, for the rest of the duration of execution, invokes undefined behavior.

一个好的解决方案也不涉及freopen,尽管您可能能够做到这一点.相反,只需使用 dup2fflush.这个答案(由我)解释了如何做到这一点:

A good solution does not involve freopen either, although you might be able to make that work. Instead, simply use dup2, with fflush. This answer (by me) explains how to do it:

https://stackoverflow.com/a/4832902/379897

用您要定向到的文件代替 "/dev/null".

Substitute the file you want to direct to in place of "/dev/null".

这篇关于通过 freopen() 重定向后恢复标准输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆