繁体   English   中英

当 POSIX 说 stderr 应该对读写开放时,它是什么意思?

[英]What does POSIX mean when it says stderr is expected to be open for reading and writing?

POSIX 在stderr、stdin、stdout 上的页面 - 标准 I/O 流是这样说的:

stderr stream 预计将开放读写。

“预期”有多强? 是否违反了未定义的行为? 它是谁的责任,系统的还是应用程序的?

考虑这个程序:

#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 读取?

Austin Group (维护 POSIX 标准的联合工作组)讨论了 2020 年 12 月 7 日和 2020 年 12 月 10 日电话会议期间报告的关于“预期是”措辞的缺陷,并同意 POSIX 问题中的措辞7(2018年版)有问题。 下一个版本的 POSIX 标准中的措辞将更改如下(从错误注释中复制):

在第 65 页第 1912 行之前(XBD“交互式外壳”)插入一个新定义并重新编号其余部分:

互动装置

终端设备。

注意:此定义旨在与 ISO C 标准对“交互设备”的使用保持一致。

在第 496 页第 17224-17228 行(XSH 2.5 标准 I/O 流)和第 2017 页第 64723-64727 行(XSH stderr、stdin、stdout 描述)更改:

在程序启动时,应预定义三个流且无需显式打开:标准输入(用于读取常规输入)、标准 output (用于写入常规输出)和标准错误(用于写入诊断输出)。 打开时,标准错误 stream 没有完全缓冲; 当且仅当可以确定 stream 不是指交互式设备时,标准输入和标准 output 流是完全缓冲的。

至:

在程序启动时,应预定义三个流并且已经打开: stdin (标准输入,用于常规输入)用于读取, stdout (标准 output,用于常规输出)用于写入,以及stderr (标准错误,用于诊断输出)用于写作。 打开时, stderr不应被完全缓冲; 当且仅当 [CX] 与 stream 关联的文件描述符被确定为不与交互式设备关联时, stdinstdout应被完全缓冲。[/CX]

在 2017 页第 64733 行(XSH 标准输入说明)上,更改:

stderr stream 预计将开放读写。

至:

这些文件描述符通常都与具有访问模式 O_RDWR 的单个打开文件描述相关联(例如,在用于登录 shell 的终端设备的情况下)。 但是,在这种情况下,不需要在程序启动时打开stderrstdinstdout流以进行读取和写入。

在 2017 页第 64747 行(stdin 另见)添加isatty ()。

特别感谢 Rich Felker 报告该缺陷。

POSIX 在execve的规范中对此进行了详细说明:

如果文件描述符 0、1 或 2 在成功调用 exec 系列函数之一后将被关闭,则实现可能会为新进程映像中的文件描述符打开一个未指定的文件。 如果执行标准实用程序或符合标准的应用程序时文件描述符 0 未打开以供读取或文件描述符 1 或 2 未打开以进行写入,则执行实用程序或应用程序的环境应被视为不符合标准,因此实用程序或应用程序的行为可能与本标准中的描述不同。

对于您自己的应用程序,如果他们尝试在其中任何一个关闭的情况下执行,他们应该为实现为他们打开新的标准输入/输出/错误的可能性做好准备,并且可以设置自己的规则(包括将其视为违反合同导致如果标准文件描述符在启动时未打开,它们将如何处理它。

对于标准实用程序,上面的文字涵盖了它。

您引用的文档只是指定它们与这些文件描述符相关联。 我同意这还不够清楚,但合理的解释是,如果相应的文件描述符在应用程序入口处未打开或未针对适当的模式打开,则结果是在相关功能下为该条件(通常是 EBADF)指定的结果. 例如, fgetc指定:

[EBADF]

[CX] [选项开始] stream 底层的文件描述符不是打开以供读取的有效文件描述符。 [选项结束]

关于“预期”的文字:

stderr stream 预计将开放读写。

我认为标准中的任何地方都没有定义“预期”。 但是,这里使用了stream这个词,而不是文件/文件描述符,所以我会将其读作stderr stream 的FILE模式(如在fopen模式中)这样,只要读取或写入函数都不会产生未定义的行为因为它们之间的切换规则得到遵守。 如果没有此文本,例如在顶部没有 POSIX 的普通文本, fgetc(stderr)可能会产生未定义的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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