用户定义的 errno 范围值(POSIX 或 Linux-特定)

User-defined errno range values (POSIX or Linux-specific)

如果可能,POSIX 的问题,否则 Linux-特定平台的问题:

  1. 是否有用户定义的errno值?(至于信号SIGUSR1SIGUSR2
  2. 如何找到系统未使用的errno值?(负值?)
  3. 如何防止strerror()中断?(检查errnum符号前?)

我的代码open()一个资源并通知另一个对象。如果发生故障(成功为零),通知 Event 会向系统传达 errno

但是也可以在我的代码中检测到失败,例如if(count>=size)。我想重用字段 Event::errnum 来传达这个失败。因此,我的用户定义的故障代码不应与系统定义的 errno 值重叠。

我找到了errno range 9000–11000 reserved for user, but this seems to be specific to Transaction Processing Facility...

请注意,我的问题 不是 关于 library-defined errno 的问题。 struct Event 没有暴露在我的代码之外。我的代码不会覆盖 errno

下面的代码片段在 but my question also applies for .

#include <cerrno>

#define E_MY_USER_DEFINED_ERROR 9999

struct Event
{
    int fd;
    int errnum;
};

struct Foo
{
    Foo( int sz ) : count(0), size(sz) {}

    Event open( const char name[] )
    {
        if( count >= size )
            return { -1, E_MY_USER_DEFINED_ERROR };

        int fd = 1; // TODO: open ressource...
        if (fd < 0) return { -1, errno };
        else        return { fd, 0 };
    }

    int count, size;
};

int main()
{
    Foo bar(0);
    Event e = bar.open("my-ressource");
    // send Event to another object...
}

实际 errno 值未由 C 和 C++ 标准定义。因此,无法 return 一个特定的(正)整数并保证它不会与实现使用的整数发生冲突。 C标准只需要三个宏:

C11 草稿,7.5 个错误

The macros are

EDOM
EILSEQ
ERANGE

which expand to integer constant expressions with type int, distinct positive values, and which are suitable for use in #if preprocessing directives;

所以您不知道在您的实现中定义了哪些其他 errno 值。

errno 值是标准 C 和 POSIX 中的正整数。因此,您可以使用自己的负值枚举来定义自己的错误编号。 但是你不能使用 strerror/perror 接口。因此,您可能需要 strerror/perror 的额外包装器来解释您自己的错误编号。

类似于:

enum myErrors{
ERR1 = -1,
ERR2 = -2,
...
ERR64 = -64
};

char *my_strerror(int e)
{
   if (e>=ERR1 && e<=ERR2)
      return decode_myerror(e); // decode_myerror can have a map for  
                                //your error numbers and return string representing 'e'.
   else
      return strerror(e);
}

perror 的类似。

请注意,您还应该在调用 "open-resource" 之前将 errno 设置为 0,以确保 errno 确实由您的函数设置。

在这种情况下,我会完全避免使用标准 errno 并定义我自己的错误枚举。如果您的 "open-resource" 不太复杂并且 return 也有可能出现错误代码,那么您可以这样做。

建议使用负值作为用户定义的范围。 这对我来说是完美的。

下面是我使用 P.P 的建议的问题片段。此代码段也可在 coliru.

上找到
#include <cerrno>
#include <cstring>
#include <iostream>

#define E_MY_USER_DEFINED_ERROR -1

struct Event
{
    int fd;
    int errnum;
};

struct Foo
{
    Foo( int sz ) : count(0), size(sz) {}

    Event open( const char name[] )
    {
        if( count >= size )
            return { -1, E_MY_USER_DEFINED_ERROR };

        int fd = std::strlen(name); // TODO: open ressource...
        if (fd < 0) return { -1, errno };
        else        return { fd, 0 };
    }

    int count, size;
};

int main()
{
    Foo bar(0);
    Event e = bar.open("my-ressource");
    std::cout << std::strerror( e.errnum ) << std::endl;
}

使用 GCC 输出

Unknown error -1

使用 Clang 输出

Unknown error -1