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

时间:2015-05-21 09:54:10

标签: c++ c linux errno user-defined

如果可能的话,POSIX的问题,否则针对特定于Linux的平台:

  1. 是否有用户定义的errno值?(对于信号SIGUSR1SIGUSR2
  2. 如何找到系统未使用的errno值?(负值?)
  3. 如何防止strerror()中断?(在errnum标志前检查?)
  4. 我的代码open()是一个资源并通知另一个对象。如果发生故障,通知Event将传达系统errno(成功时为零)。

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

    我找到errno range 9000–11000 reserved for user,但这似乎特定于Transaction Processing Facility ...

    请注意,我的问题是 关于library-defined errnostruct Event未在我的代码之外公开。我的代码不会覆盖errno

    以下代码段位于,但我的问题也适用于

    #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...
    }
    

2 个答案:

答案 0 :(得分:2)

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

C11草案,7.5错误

  

宏是

     

益登
  EILSEQ
  ERANGE

     

扩展为类型为int,distinct的整型常量表达式   正值,适用于#if预处理   指令;

因此,您不知道在您的实施中定义了哪些其他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的类似内容。

请注意,在致电&#34; open-resource&#34;之前,您还应将errno设置为0。确保errno确实是由你的职能设定的。

我在这种情况下完全避免使用标准错误,并定义我自己的错误枚举。你可以这样做,如果你的&#34;开放资源&#34;并不太复杂,并且可能返回错误代码。

答案 1 :(得分:0)

Blue Moon's answer建议使用负值作为用户定义的范围。 这在我的案例中是完美的。

以下是我的问题片段,使用了他的建议。此代码段也可在coliru上找到。

define(function(require){
    'use strict';

    var Backbone = require('backbone'),
        JST = require('templates')

    return Backbone.View.extend({
        model: require('globals/session'),
        ...
    });
});

使用GCC输出

#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;
}

使用Clang输出

Unknown error -1