fflush(NULL)不刷新stdin是否违反POSIX标准?
fflush(NULL)不刷新stdin是否违反POSIX标准?
考虑以下代码片段:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { char line[128] = {0}; fgets(line, sizeof(line), stdin); puts(line); fflush(NULL); pid_t pid = fork(); if (pid == 0) { fgets(line, sizeof(line), stdin); puts(line); exit(EXIT_SUCCESS); } else { waitpid(pid, NULL, 0); fgets(line, sizeof(line), stdin); puts(line); } return 0; }
当通过文件重定向传入包含3行内容的文件时,程序在macOS和Linux上表现出差异:
$ cat test line 1 line 2 line 3 macOS $ ./a.out < test line 1 line 2 line 3 Linux $ ./a.out < test line 1 line 2 line 2
差异的核心原因是glibc的fflush(NULL)不会刷新stdin,尽管fflush(stdin)的行为在标准中有明确规定。
glibc手册中的说明:
如果
stream是空指针,fflush会刷新所有打开的输出流的缓冲输出。
而POSIX标准的相关规定:
对于以读取模式打开且关联文件描述符的流,如果文件尚未到达EOF,且该文件支持定位,则应将底层打开文件描述符的文件偏移量设置为流的文件位置,同时丢弃所有通过
ungetc()或ungetwc()推回流中但尚未被读取的字符(不会进一步修改文件偏移量)。
如果stream是空指针,fflush()应对所有符合上述行为定义的流执行此刷新操作。
从POSIX标准的明确要求来看,glibc和musl实现的fflush(NULL)仅处理输出流、忽略输入流的行为确实违反了标准。POSIX要求空指针参数时,fflush需要同步所有符合条件的输入流的文件偏移量并丢弃推回字符,而非仅处理输出流。
内容的提问来源于stack exchange,提问作者SuibianP
相关产品推荐
相关产品推荐

