9

我正在编写一个程序,其中大多数使用的库函数在错误时返回 -1 并设置 errno。程序的行为是,如果发生错误,它就会退出。为了确定程序外部的确切退出点和错误(使用示例gdb),我想使用以下方法:

err = func_1(..arglist_1..);
if(err != 0)
{
    perror("func(..arglist..)");
    return ((1u << 8) | errno);
}
//..
//.. some more funcs
//..
err = func_n(..arglist_n..);
if(err != 0)
{
    perror("func(..arglist_n..)");
    return (((unsigned)n << 8) | errno);
}

这里的问题是安全假设。

现实: errno被声明为extern int errno;内部errno.h
假设 1:errno的值始终小于 255。
假设 2: errno始终为正。

根据 中定义的所有误差常数(EAGAIN 等)errno.h,这些假设目前是正确的。这些在未来也能被假设为真的吗?

PS:我不想靠perror()判断退出点。

4

1 回答 1

13

您的程序的退出状态限制为 0..255,因此如果这些返回语句来自main()程序,则高位无关紧要。

C 标准(ISO/IEC 9899:2011 §7.5 错误<errno.h>)说:

errno
它扩展为具有 int 类型和线程本地存储持续时间的可修改左值201),其值由几个库函数设置为正错误数。

201)errno不必是对象的标识符。它可能会扩展为函数调用产生的可修改左值(例如,*errno())。

C 标准期望错误为正数。POSIX(IEEE Std 1003.1,2013 版)状态<errno.h>

<errno.h>头应定义以下宏,这些宏应扩展为具有类型的整数常量表达式int,不同的正值(除了以下说明),并且应适用于#if预处理指令: ...

因此,您可以合理地安全地假设(系统生成的)错误编号为正数,但您的代码可以设置为errno负数(或零)。目前,没有 POSIX 系统生成的错误数高于 200,因此假设它们将被限制在 255 在短期内是安全的,但从长远来看可能不是。他们没有理由受到如此有限的限制。

您声称的“现实”仅适用于非线程程序。如果您正在编译线程支持,那么errno不会简单地声明为extern int errno;,并且在任何情况下都不应尝试errno为自己声明。声明它的唯一安全方法是通过<errno.h>标头。

于 2013-08-21T07:30:15.387 回答