[英]Strange issue redirecting output using dup2 sys call
使用dup2系统调用将STDOUT重定向到文件时遇到一个奇怪的问题。
我正在使用2个在这里找到的函数: 在C语言中,当执行execvp()或类似调用时,如何将stdin / stdout / stderr重定向到文件?
下面是我编写的一个简单程序,用于在出现错误后测试功能。 该程序将按预期工作,并将输入内容写入文件。
int fd;
fpos_t pos;
int main(){
while(1){
char input[100];
printf("Please enter text: ");
gets(input);
printf("\nString = %s\n", input);
switchStdout("test.txt");
puts("THIS TEXT SHOULD REDIRECT\n");
printf("String(file) = %s\n", input);
revertStdout();
puts("This should come before the gets() ??\n");
}
return 0;
}
void switchStdout(const char *newStream)
{
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen(newStream, "w", stdout);
return;
}
void revertStdout()
{
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos);
}
调用revertStdout()函数后,该程序似乎挂起。
我意识到,实际上,程序在打印“这应该在gets()之前?”之前调用过gets()。
输入文本后,程序将打印跳过的行。
这是终端输出,我以粗体输入:
请输入文字: 您好!
字符串=你好!!!!
为什么我可以在这里输入?
这应该在gets()之前?请输入文字:
字符串=为什么我可以在这里键入?
抱歉,帖子很长。 程序将按预期方式写入文件。
感谢您提供任何帮助。
基本上,当您在标准库的背后偷偷摸摸时,就会发生这种情况。
报价man setbuf
:
通常,所有文件都是块缓冲的。 当对文件执行第一次I / O操作时,将调用
malloc(3)
,并获得一个缓冲区。 如果一个流指向一个终端(如stdout
通常那样),则它是行缓冲的。
因此,您的stdout
开始引用您的终端,并进行行缓冲。 然后,你freopen
它来指一个文件,因此(因为重新打开流的一部分),它成为块缓冲的。 然后,您将dup2
fd,所以现在它再次指向终端,但它仍然是相同的流; 标准库无法知道您已经了解了stdout
并更改了它的引用。 因此,它保持块缓冲状态,从而导致意外行为。
在第一个输出之后更改流的缓冲会导致未定义的行为,尽管对于某些C库实现,缓冲区是否为空也是可能的(因为在调用fflush
)。 您不应该指望这种行为。 但是,您可以在dup2
之后立即再次freopen
stdout
流,将第一个NULL传递给freopen
,从而使标准库有机会重新初始化。
就其价值而言,由于freopen
有效地关闭了流,因此在switchStdout
进行fflush
调用是不必要的。 如果将freopen
添加到revertStdout
,它将重置错误和文件结束指示符,因此您可以删除对clearerr
的调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.