Ответ 1
Это немного устарело, но errno - manual section 3 говорит, что вы можете напрямую назначить ему, даже если это макрос, и он будет нитью локальный
Я пишу модуль, который экспортирует интерфейс, похожий на send
и recv
.
Так как эти функции должны возвращать соответственно количество отправленных и полученных байтов, я не могу выполнять правильное управление ошибками, как обычно, (например, используя перечисления и возвращающие мнемонические значения).
В такой ситуации я должен установить errno
, как это делает стандартная библиотека? Если это так, поскольку errno
является конкретным потоком, есть ли способ записи на нем или я могу просто присвоить ему значение?
Изменить: эксперимент. Я заметил, что настройка errno
по назначению работает. Тем не менее: безопасен ли он и переносится для любой системы?
Это немного устарело, но errno - manual section 3 говорит, что вы можете напрямую назначить ему, даже если это макрос, и он будет нитью локальный
Вы можете не только установить errno
, во многих случаях вы должны установить errno
. При вызове некоторых функций библиотеки вы можете только достоверно обнаружить ошибку, если вы сначала установите errno
на ноль. См. strtol
для примера.
Из спецификации POSIX strtol
:
[CX] [Option Start] Функция strtol() не должна изменять настройку errno в случае успеха.
Так как 0, {LONG_MIN} или {LLONG_MIN} и {LONG_MAX} или {LLONG_MAX} возвращаются при ошибке, а также верны успешные результаты, приложение, желающее проверить наличие ошибок, должно установить errno в 0, затем вызвать strtol() или strtoll(), затем проверьте errno. [Option End]
Собственно, вы, вероятно, можете сделать "правильное" (как вы выразите) управление ошибками, так как вы вернете int
.
Просто используйте неотрицательные значения для количества прочитанных или записанных байтов и отрицательных значений для кодов ошибок. Вам не нужно ограничивать себя -1
:
enum myerrors {
ERR_NO_MEMORY = -1,
ERR_BAD_ARGS = -2,
ERR_CPU_EXPLODED = -3,
// and so on
};
Однако установка errno
по вашему желанию действительна. Стандарт утверждает, что errno
расширяется до изменяемого значения lvalue, что означает, что вы можете его установить. От C1x/n1425, 7.5 Errors <errno.h>
:
... и
errno
, который расширяется до модифицируемого значения l, которое имеет тип int, значение которого устанавливается на число положительных ошибок несколькими библиотечными функциями.
Вы можете просто присвоить значение errno
, но имейте в виду, что есть другие способы сигнализировать об ошибке, которая в зависимости от вашей ситуации может быть более подходящей:
int *
(или size_t *
или тем, что вы используете). Затем вы можете вернуть код ошибки.От: http://support.sas.com/documentation/onlinedoc/sasc/doc700/html/lr1/errno.htm
Единственными переносимыми значениями для
errno
являютсяEDOM
иERANGE
Итак, чтобы ответить на вопрос о переносимости.
Да, вы можете назначить ему, и да, назначение будет потокобезопасным. См. Является ли errno потокобезопасным?