如果我正在编写代码。
#include<stdio.h>
int main()
{
int i;
FILE *fp;
fp=fopen("shiv.txt","w");
printf("%d",fileno(fp));
dup2(3,1);
fprintf(fp,"hello");
}
作为输出,程序正在hello3
文件中打印shiv.txt
我们可以看到printf
首先被调用,但其输出显示在fprintf
的输出之后。
此外,在dup2
语句后调用printf
因此printf
的输出应放在终端上
答案 0 :(得分:1)
标准I / O流被缓冲 - 可能的例外是标准错误流,只有POSIX不需要完全缓冲。如果没有调用fflush(stdout)
来刷新标准输出的输出缓冲区(或者如果它是行缓冲的那样,则是换行序列的输出),没有定义关于FILE
接口的工作方式一旦你拨打dup2
。
由于dup2
适用于文件描述符而不是FILE
指针,因此您遇到了问题:POSIX没有指定在这种情况下要执行的操作。与stdout
关联的缓冲区可能会被丢弃,也可能会像fclose
一样被刷新。缓冲区甚至可以保持关联,而不是刷新/丢弃,因为从stdout
接口的角度来看,FILE
仍处于打开状态。
因此,如果不将FILE
接口与基础文件描述同步,则行为不一定是确定性的(在fclose(stdout)
之后添加dup2
调用)。此外,除stderr
stdout
以及与您打开的文件的文件说明相关联的dup2
之外,还会发生什么?行为是按dup2
调用的顺序,与队列相反,还是与堆栈相反,甚至是看似随机的顺序,后者表明可能存在段错误?如果您dup2(STDERR_FILENO, STDOUT_FILENO)
,后跟dup2(fileno(fp), STDERR_FILENO)
,输出顺序是多少?写入标准输出/错误缓冲区的结果是出现在fprintf结果之前还是之后或混合(或有时是一个,有时是另一个)?哪个首先出现 - 写入stderr的数据或写入stdout的数据? 你能否确定这一切都会按顺序发生?
答案可能不会让您感到惊讶:不会。在一个配置上发生的情况可能与另一个配置上发生的情况不同,因为文件描述符,标准流使用的缓冲区和标准流的FILE接口之间的交互未定义。
正如@twalberg评论的那样,无法保证您打开的文件是文件描述符3,因此在对这样的数字进行硬编码时要小心。此外,您STDOUT_FILENO
提供<unistd.h>
,这是dup2
实际声明的位置,因此您可以避免使用fileno
来代替文件描述符1它