【发布时间】:2020-09-15 01:44:04
【问题描述】:
POSIX 在stderr, stdin, stdout - standard I/O streams 上的页面是这样说的:
stderr 流应该是开放读写的。
“预期”有多强?是否违反了未定义的行为?又是谁的责任,系统的还是应用的?
考虑这个程序:
#include <stdio.h>
int main(void) {
printf("feof is %d and ferror is %d\n", feof(stderr), ferror(stderr));
printf("fgetc is %d\n", fgetc(stderr));
printf("feof is %d and ferror is %d\n", feof(stderr), ferror(stderr));
}
当我在不重定向 stderr 的情况下运行它(所以它像 stdin 一样指向我的终端),它会立即输出它而不等待任何输入:
feof is 0 and ferror is 0
fgetc is -1
feof is 0 and ferror is 1
这是否意味着我的系统不符合 POSIX?
另外,如果这是我的责任,那么假设我有一个权限为620 的文件,并且我在组中但不是所有者。这是否意味着 someprogram 2>saidfile 是未定义的行为,因为无论如何您都无法从 stderr 读取?
【问题讨论】:
-
传统上,
login命令(或在login之前运行的getty程序)将打开tty 设备进行读写作为文件描述符0(标准输入),并使用@987654329 @ 创建文件描述符 1(标准输出)和 2(标准错误)。因此,login启动的 shell 可能具有所有三个可读写的标准 I/O 描述符(但 I/O 流可能不那么灵活)。我不知道 POSIX 要求;它在第 6 期(POSIX 2004)中正式添加。系统(shell)将负责提供可读的stderr。 -
@JonathanLeffler 但是即使 FD 2 可以读写,尝试从
stderr流中读取也会失败(如果我想让它工作,我必须直接使用 FD)。这似乎正是 POSIX 所说的不应该发生的事情。 -
还有一点很奇怪的是“此参考页面上描述的功能与 ISO C 标准一致”的注释,但 ISO C 不包含这样的要求。
-
我正在扩展我认为需求的来源;我无法解释它,我对
stderr(不同于“标准错误”)可读可写的规范感到困惑。当然,对于文件流,您应该在读取和写入之间或在写入和读取之间使用定位操作(例如fseek(stderr, 0L, SEEK_CUR))。我注意到 POSIX 没有说明stdin或stdout是否需要既可读又可写。要求在 POSIX 扩展部分:[CX] ⌦ ... ⌫ — 它是对标准 C 的纯扩展。 -
如果这里有不一致的地方,这似乎是 C 库的错,即使 fd 2 已打开以供读取,也拒绝接受 stderr 上的读取。我的系统(Ubuntu 19.1 上的 glibc)也是这样做的。但无论如何,这不是外壳的错。
标签: c file language-lawyer posix stderr