【发布时间】:2017-01-03 04:38:30
【问题描述】:
名为get1的C语言简单测试程序:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void) {
errno = 0;
int ch = fgetc(stdin);
printf("ch = %d\n", ch);
if (errno)
printf("errno = %d: %s\n", errno, strerror(errno));
return 0;
}
它只打印以十进制读取的第一个字节,然后如果errno 不为零,则显示errno 和相关的错误消息。
一些结果(foo 是一个文本文件,empty 是一个长度为零的文件):
% ./get1 < foo
ch = 104
% ./get1 < empty
ch = -1
好的,正如预期的那样。然而:
% ./get1 < /dev/zero
ch = 0
errno = 25: Inappropriate ioctl for device
% ./get1 < /dev/null
ch = -1
errno = 25: Inappropriate ioctl for device
% ./get1 < /dev/random
ch = 196
errno = 25: Inappropriate ioctl for device
读取工作正常,但是当我从这些设备中读取时,它设置为errno。为什么?
那是在 macOS(达尔文)上。我在 Linux (Debian) 和 NetBSD 上得到了同样的结果,除了 /dev/random 的不同错误(其他设备上的错误与 macOS 上的相同):
% ./get1 < /dev/random
ch = 170
errno = 22: Invalid argument
我的理解是,如果你没有得到EOF,那么就没有错误。如果你得到EOF,那么你检查errno 看看是否有错误。在所有这些情况下,从设备获取字节似乎都没有错误,也不应该有。然而errno 已设置。
(删除printf 不会改变任何东西,以防有人想知道。)
事实证明,errno 在 AIX、SunOS 或 OpenSUSE 上从此类设备读取时未设置。
那么这里的交易是什么?这是一个错误,尽管很普遍?这是可接受的行为吗?这是预期的行为吗?为什么设置errno?
【问题讨论】: