繁体   English   中英

使用dup2 sys调用重定向输出的奇怪问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM