Определяемые пользователем значения диапазона errno (POSIX или Linux)
Вопросы для POSIX, если это возможно, иначе для платформ, специфичных для Linux:
- Есть ли пользовательский
errno
ценности? (что касается сигналовSIGUSR1
а такжеSIGUSR2
) - Как найти
errno
значение не используется системой? (отрицательные значения?) - Как предотвратить
strerror()
перерыв? (проверьте передerrnum
знак?)
Мой код open()
ресурс и уведомляет другой объект. Уведомление Event
передает систему errno
если происходит сбой (ноль при успехе).
Но ошибки также могут быть обнаружены в моем коде, например, if(count>=size)
, И я хочу повторно использовать поле Event::errnum
передать эту неудачу. Поэтому мой определяемый пользователем код ошибки не должен перекрывать системный errno
ценности.
я нашел errno
диапазон 9000–11000 зарезервирован для пользователя, но это, похоже, характерно для средства обработки транзакций...
Обратите внимание, что мой вопрос не о том, что определено в библиотеке. struct Event
не выставляется вне моего кода. Мой код не перезаписывается errno
,
Ниже приведен фрагмент кода на C++, но мой вопрос также относится к c.
#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 ответа
Настоящий 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 в подобных ситуациях и определял бы свое собственное перечисление для ошибок. Вы можете сделать это, если ваш "открытый ресурс" не слишком сложен и возвращает слишком возможные коды ошибок.
В ответе Blue Moon предлагается использовать отрицательное значение в качестве пользовательского диапазона. Это идеально в моем случае.
Ниже приведен фрагмент моего вопроса с использованием его предложения. Этот фрагмент также доступен на 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