【问题标题】:Is it safe to assume errno to be always positive?假设 errno 总是积极的是否安全?
【发布时间】:2013-08-23 10:51:09
【问题描述】:

我正在编写一个程序,其中大多数使用的库函数在错误时返回 -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);
}

这里的问题是安全假设。

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

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

P.S.:我不想依赖perror() 来确定退出点。

【问题讨论】:

  • 我怀疑这两种假设都是安全的。对于第二个,你认为0 是肯定的吗?
  • 没有0 被排除在外,因为this link here 说:No function in this volume of IEEE Std 1003.1-2001 shall set errno to 0.
  • 仅仅因为标准库中没有函数将其设置为0,并不意味着其他人不会将其设置为0。对于某些标准库函数,判断调用是否失败的唯一方法是先将errno设置为0,然后看看函数做了什么。
  • @jxh:你是对的,Jonathan Leffler 的回答解释了我的一切。是的,我在某处研究过那些成功返回 -1 的函数,并且只能通过将 errno 设置为 0 来检查错误。
  • @jxh:尤里卡!!找到了!! getpriority() :-)就是这类函数的一个例子。

标签: c x86-64 errno suse


【解决方案1】:

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

C 标准(ISO/IEC 9899:2011 §7.5 错误&lt;errno.h&gt;)说:

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

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

C 标准期望错误是正数。 &lt;errno.h&gt; 的 POSIX(IEEE Std 1003.1,2013 版)状态:

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

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

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

【讨论】:

  • 好的,我得到了答案,谢谢 Jonathan Leffler。首先,他是对的,我打算在 main() 中这样做。接下来,我的错误是我忘记了多线程程序。我还使用了older copy of the standard 作为参考,没有提到它总是积极的。
  • C89 没有规定错误数是正数(只是非零); C99 确实规定错误编号为正数。有趣的是,POSIX 1997 说“&lt;errno.h&gt; 标头为 errno 提供了声明,并为以下符号常量提供了非零值。”这与当时的 C89 (C90) 标准一致。
  • @nishant:有趣——你链接到errno 的 POSIX 2004 页面,它没有提到“积极”(errno 的 POSIX 2013 页面也没有),而我链接到&lt;errno.h&gt; 的 POSIX (2013) 页面,其中确实提到了它(标题的 POSIX 2004 页面也是如此)。我想我很幸运选择了合适的地方看;我不知道不对称。
猜你喜欢
  • 2010-09-19
  • 2016-12-13
  • 2012-05-27
  • 2011-09-26
  • 1970-01-01
  • 2011-02-27
  • 2017-02-26
  • 2020-07-01
  • 1970-01-01
相关资源
最近更新 更多