如何将UNIX中的errno转换成对应的字符串?

问题描述 投票:0回答:6

UNIX 中是否有任何函数可以将 errno 转换为其对应的字符串,例如EIDRM 到“EIDRM”。调试检查这些整数 errnos 的错误非常烦人。

unix errno
6个回答
76
投票

strerror()
应该这样做。 http://linux.die.net/man/3/strerror

仅供参考,这样您就可以自己更轻松地找到这些东西:如果您键入 man errno (或您正在研究的任何函数),然后查看手册页的最底部,您将看到相关函数的列表.如果您

man
其中的每一个(根据他们的名字猜测先做哪一个),您通常会找到类似问题的答案。


14
投票

只是另一个完全解决您遇到的问题的解决方案,但在 Python 而不是 C:

>>> import errno
>>> errno.errorcode[errno.EIDRM]
'EIDRM'

11
投票

现在有一个

errno
实用程序与 moreutils 包一起分发。

$ errno -h
Usage: errno [-lsS] [--list] [--search] [--search-all-locales] [keyword]

$ errno -l
EPERM 1 Operation not permitted
ENOENT 2 No such file or directory
ESRCH 3 No such process
EINTR 4 Interrupted system call
EIO 5 Input/output error
ENXIO 6 No such device or address
E2BIG 7 Argument list too long
ENOEXEC 8 Exec format error
...

$ errno 11
EAGAIN 11 Resource temporarily unavailable

$ errno -s Ouput
EIO 5 Input/output error

4
投票

我不确定这种

enum
风格的名称,但出于调试和错误报告的目的,您可以使用
perror(3)
strerror(3)
C 函数返回错误代码的人类可读表示。有关详细信息,请参阅手册页。


3
投票

如果您确实需要 EIDRM 而不是它的错误字符串:否。然而,在 OpenBSD 上,

man errno|egrep ' [0-9]+ E[A-Z]+'|sed 's/^ *//'|cut -d' ' -f1,2

打印出一张漂亮的表格“...... 第89话 ...”,您可以将其进一步转换为您希望在其中具有此功能的编程语言的数据结构。


2
投票

我最近写了

errnoname
它可以让你做到这一点。

在 UNIX 中没有执行此操作的标准函数。 (GNU 的 glibc 有

strerrorname_np
,但目前没有其他 C 库提供它,所以它甚至不能在所有 Linux 发行版上使用,更不用说其他任何地方了。)

strerror
(还有
strerror_r
strerror_l
perror
)打印关于错误是什么的“人性化”提示,但它们的输出是

  • 通常没有证件,
  • 不规范,
  • 不保证遵守任何长度或格式限制,
  • 通常因区域设置而异,并且
  • 并不总是在所有情况下都有意义(例如,他们倾向于为
    File exists
    打印
    EEXIST
    ,即使对于不是文件的东西经常返回该错误)。

这意味着它们表面上是用户友好的,但是

  • 其他代码无法可靠地解析它们(对于自动化、监控、脚本、包装程序等而言更糟),
  • 在边缘情况下会产生误导,并且
  • 妨碍技术经验丰富的用户。

具有讽刺意味的是,没有任何东西阻止那些函数在所有情况下都只使用

errno
符号名称作为它们的错误字符串——这将在标准的字母范围内,特别是如果它们只针对特定的语言环境,比如特殊
C
语言环境。但据我所知,没有 libc 会这样做。

无论如何,由于我的

errnoname
是在“零条款BSD许可证”(0BSD)下发布的,这是一个宽松的许可证,或者更准确地说是一个公共领域等效许可证,你可以用它做任何你想做的事。

为了使这个答案独立,同时仍然符合答案字符限制,下面是

errnoname
函数的两个缩写变体。

errnoname
中它们都实现了,但在这里我将每个的要点分开以使它们更具可读性。

注意事项:

  1. 这涵盖了 Linux、Darwin(Mac OS X 和 iOS X)、FreeBSD、NetBSD、OpenBSD、DragonflyBSD 和几个闭源 Unix 的全部或大部分

    errno
    名称,截至 2020 年 1 月开始。

  2. 如果你给它一个它不知道名字的

    errno
    值,它会返回一个空指针。

变体 1:简单、通用

这个非常便携且简单,无需担心边缘情况。它几乎可以使用任何 C89 或更好的编译器进行编译。 (甚至可能是 C++ 编译器,随着语言的不同,这种情况变得越来越少。)

这个变体可以编译成非常有效的代码(数组查找而不是switch语句)当优化调得足够高时,现代编译器,但可能不取决于具体情况。

#include <errno.h>

char const * errnoname(int errno_)
{
    switch(errno_)
    {
#ifdef E2BIG
        case E2BIG: return "E2BIG";
#endif
#ifdef EACCES
        case EACCES: return "EACCES";
#endif
/*
    repeat for the other 100+ errno names,
    don't forget to handle possible duplicates
    like EAGAIN and EWOULDBLOCK
*/
    }
    return 0;
}

变体 2:非常高效,适用于大多数系统

这个更 obviously 高效,并且会非常可靠地编译成高效代码,因为它使数组查找明确并且不依赖于计算机优化。

只要系统具有正值、相对较小且合理连续的

errno
值,就可以安全使用。

只能在为数组实现乱序指定初始化器的编译器上编译(C99 或更高版本,不包括到目前为止的所有 C++ 版本。)

#include <errno.h>

char const * errnoname(int errno_)
{
    static char const * const names[] =
    {
#ifdef E2BIG
        [E2BIG] = "E2BIG",
#endif
#ifdef EACCES
        [EACCES] = "EACCES",
#endif
/*
    repeat for the other 100+ errno names,
    don't forget to handle possible duplicates
    like EAGAIN and EWOULDBLOCK
*/
    };
    if(errno_ >= 0 && errno_ < (sizeof(names) / sizeof(*names)))
    {
        return names[errno_];
    }
    return 0;
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.