这是How to capture output of printf?的后续活动-特别是jxh的答案。
我在回答Viesturs在2018年遇到的问题时遇到了与代码相同的麻烦。有人建议他打开一个新问题,他说他的帐户不允许这样做,所以我要开设一个同样的问题。
关于这个答案,最初的提问者在2012年说它有效。 Viesturs在2018年说,在代码运行之后,进一步的输出既没有出现在控制台上,也没有出现在重定向的文件中。
我遇到了同样的问题。使用以下代码,this shouldn't be redirected\n
不会显示在控制台上,也不会出现在重定向的文件中。重定向的文件仅包含第一行。
我正在使用gcc 8.3.0,还尝试了gcc 6.5.0。 glibc 2.29。
请注意,我不想以后再使用freopen
"CON"
。即使可行,我仍要保留原始的stdout,因为它本身可以是重定向。 (尽管在我的测试中,它只是控制台。)
或者:jxh答案中有一个错误;我犯了同样的错误,维斯特斯是;或(我最好的猜测)早于gcc 6.5.0或glibc 2.29引入(或修复了)错误。
已重定向。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
答案 0 :(得分:3)
对此没有正确的解决方案可以涉及:
stdout
,因为stdout
不是变量/左值。它是一个宏,扩展为类型FILE *
的表达式。如果它碰巧也是左值,那么这是发生它的任何特定实现的实现细节,而不是语言的一部分。fclose(stdout)
,因为在fclose(stdout)
之后,在程序的其余时间内,stdout
在程序中任何位置的任何进一步使用(隐式(例如printf
)或显式)执行,调用未定义的行为。一个好的解决方案也不会涉及freopen
,尽管您有能力能够做到这一点。相反,只需将dup2
与fflush
一起使用。这个答案(由我本人)解释了如何做到:
https://stackoverflow.com/a/4832902/379897
用您要定向的文件代替"/dev/null"
。
答案 1 :(得分:2)
在通过stdin
重新分配原始文件后,不能保证有任何方法可以将freopen()
重新连接到原始文件。特别是,没有指定stdin
宏是否扩展为可修改的左值,更不用说分配给结果的效果了。实际上,这首先就是freopen()
的原因。
您尝试使用的方法是合理的,但又不能保证一定能奏效,并且我观察到您描述的相同行为。可能您的printf
版本和我的版本在stdout
的标识方面进行了优化,因此,给该符号分配新值不会影响该功能的输出目标,在打印之前要关闭该功能。>
您正在使用POSIX接口(dup
和dup2
),并且在符合POSIX的实现中,最可能的工作方法是避免关闭stdin
,而是重新定义仅通过dup2()
写入的文件。在这种情况下,您应该注意fflush()
,这样的交换之前是这样的:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void funcB() {
printf("this should be redirected\n");
fflush(stdout);
}
int main() {
int stdout_fd = dup(STDOUT_FILENO);
int rd_fileno = open("/tmp/redirected", O_WRONLY | O_CREAT | O_TRUNC, 0600);
dup2(rd_fileno, STDOUT_FILENO);
funcB();
fflush(stdout);
dup2(stdout_fd, STDOUT_FILENO);
close(stdout_fd);
printf("this shouldn't be redirected\n");
fflush(stdout); // shouldn't make a difference if this is here
}
该版本确实对我有用,它与POSIX中的重定向通常具有相同的基础。特别注意stdout
永远不会关闭(程序终止时自动关闭)。