Определяемые пользователем значения диапазона errno (POSIX или Linux)

Вопросы для POSIX, если это возможно, иначе для платформ, специфичных для Linux:

  1. Есть ли пользовательский errno ценности? (что касается сигналов SIGUSR1 а также SIGUSR2)
  2. Как найти errno значение не используется системой? (отрицательные значения?)
  3. Как предотвратить strerror() перерыв? (проверьте перед errnum знак?)

Мой код open() ресурс и уведомляет другой объект. Уведомление Event передает систему errno если происходит сбой (ноль при успехе).

Но ошибки также могут быть обнаружены в моем коде, например, if(count>=size), И я хочу повторно использовать поле Event::errnum передать эту неудачу. Поэтому мой определяемый пользователем код ошибки не должен перекрывать системный errno ценности.

я нашел errno диапазон 9000–11000 зарезервирован для пользователя, но это, кажется, специфично для Средство обработки транзакций

Обратите внимание, мой вопрос не около определенный библиотекой errno. struct 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...
}

3

Решение

Настоящий errno значения не определены стандартами C и C ++. Таким образом, нет способа вернуть определенное (положительное) целое число и гарантировать, что оно не будет конфликтовать с тем, которое использует реализация.
Стандарт C требует только три марко:

C11 осадка, 7,5 ошибок

Макросы

EDOM
EILSEQ
ERANGE

которые расширяются до целочисленных константных выражений с типом int, отличный
положительные значения и которые подходят для использования при предварительной обработке #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,

Обратите внимание, вы также должны установить errno в 0 перед вызовом вашего «открытого ресурса», чтобы убедиться, что errno был действительно установлен вашей функцией.

Я бы вообще избегал стандартного errno в подобных ситуациях и определял бы собственное перечисление для ошибок. Вы можете сделать это, если ваш «открытый ресурс» не слишком сложен и возвращает слишком возможные коды ошибок.

2

Другие решения

Ответ Голубой Луны предлагает использовать отрицательное значение в качестве пользовательского диапазона. Это идеально в моем случае.

Ниже приведен фрагмент моего вопроса с использованием его предложения. Этот фрагмент также доступен на 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
0

По вопросам рекламы [email protected]