由于errno
历史原因1,C库未设置为0 。POSIX不再声称它的库在成功的情况下不会改变其值,新的Linux手册页errno.h
反映了这一点:
该<errno.h>
头文件定义了整型变量errno
,它是由系统调用,并在出现错误的情况下,一些库函数来表示什么地方出了错设置。仅当调用的返回值指示错误时(即,-1
来自大多数系统调用;-1
或NULL
来自大多数库函数),其值才有意义。这成功的功能是允许改变errno
。
在ANSI C的理由指出,委员会认为这是更实际的采用和规范使用的现行做法errno
。
errno
通常以设置为中心的错误报告机制充其量是可以容忍的。它需要库函数之间的``病理耦合'',并利用静态可写存储单元,这会干扰可共享库的构建。但是,委员会宁愿标准化这种现有的但不足的机制,而不是发明更雄心勃勃的东西。
除了检查是否已errno
设置以外,几乎总有一种检查错误的方法。errno
由于某些调用需要调用单独的API才能获取错误原因,因此检查设置是否总是不可靠。例如,ferror()
如果您从fread()
或得到短结果,则用于检查错误fwrite()
。
有趣的是,您的使用示例strtod()
是errno
在要求正确地检测是否发生错误的调用之前将其设置为0 的情况之一。所有的strto*()
字符串到数字函数都具有此要求,因为即使遇到错误也会返回有效的返回值。
errno = 0;
char *endptr;
double x = strtod(str1, &endptr);
if (endptr == str1) {
/*...parse error */
} else if (errno == ERANGE) {
if (x == 0) {
/*...underflow */
} else if (x == HUGE_VAL) {
/*...positive overflow */
} else if (x == -HUGE_VAL) {
/*...negative overflow */
} else {
/*...unknown range error? */
}
}
上面的代码基于strtod()
Linux上记录的行为。C标准仅规定下溢不能返回大于最小正数的值double
,并且是否将errno
其设置ERANGE
为实现定义2。
实际上,有大量的证书咨询文章,建议始终errno
在调用库之前将其设置为0,并在调用指示发生故障后检查其值。这是因为errno
即使调用本身成功,也会设置一些库调用3。
errno
程序启动时的值为0,但是任何库函数都不会将其设置为0。errno
可以通过库函数调用将是否存在错误设置为非零值,前提errno
是在C标准的函数说明中未记录对的使用。对于程序来说,errno
仅在报告错误后才检查其内容是有意义的。更准确地说,errno
只有在设置errno
了错误的库函数返回错误代码后,该变量才有意义。
1.以前我声称这是为了避免掩盖先前调用中的错误。我找不到任何证据支持这一说法。我也有一个伪造的printf()
例子。
2.感谢@chux指出这一点。参考是C.11§7.22.1.3¶10。
3. @KeithThompson在评论中指出。
errno
,可以随时将其设置为零。