Использование errno для отчетов об ошибках приложения / библиотеки

Я пишу библиотеку C для программного проекта. Мне нужно сделать некоторые отчеты об ошибках, но я немного ленив, чтобы реализовать свой собственный сложный набор кодов ошибок, переменных и функций. Допустимо ли использовать средство errno, предоставляемое libc, для настраиваемого сообщения об ошибках? Все мои ошибки попадают в категории, заданные макросом E....

Например, предположим, что мой код включает функцию, которая считывает хэш SHA256 в шестнадцатеричной системе счисления и преобразует его в какой-то внутренний формат. Я хочу использовать errno, чтобы сообщать об ошибках:

#include <errno.h>

int hash_fromstr(hash_t *out, const char *in) {
  /* ... */

  if (strlen(in) != 65) {
    errno = EINVAL;
    return -1;
  }

  /* ... */
}

Конечно, этот пример до смешного упрощен, в действительности гораздо больше ошибок может произойти в других функциях.


person fuz    schedule 14.05.2012    source источник
comment
Пока ваша библиотека может выдавать стандартные коды ошибок, не нарушая надлежащего функционирования errno в других частях пользовательского приложения, связанного с вашей библиотекой, я не вижу в этом проблемы. Возможно, вы могли бы использовать переменную errno, но не изменять ее и не возвращать ее копию?   -  person Chimera    schedule 15.05.2012
comment
@Jim Я хочу использовать errno для ошибок, которые возникают внутри самой библиотеки - не обязательно в функции libc, вызываемой библиотекой.   -  person fuz    schedule 15.05.2012
comment
Так вы спрашиваете, можно ли установить значение errno, чтобы сообщать об ошибках вызывающей стороне вашей библиотеки? В таком случае вы можете проверить stackoverflow.com/questions/9856822/should-i-set-errno < / а>   -  person Chimera    schedule 15.05.2012
comment
@ Джим. Это именно то, что я пытаюсь сделать.   -  person fuz    schedule 15.05.2012


Ответы (2)


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

person Chimera    schedule 14.05.2012

Да, вы можете изменить его, и он имеет область потока, что очень желательно при такой обработке ошибок.

Использование семейства ошибок errno (E...) и, возможно, его расширение может быть очень мощным, но простым шаблоном обработки ошибок. Другие могут посчитать это дурным подходом, но IMHO он дает более чистый код и стандартизированный шаблон для обработки ошибок.

person Felipe Lavratti    schedule 28.10.2014
comment
Как можно расширить errno? Насколько мне известно, нет портативного способа узнать, какие значения errno не распределены, и даже если вы это сделаете, вы получите конфликт с другими библиотеками, которые пытаются сделать то же самое. - person fuz; 28.10.2014
comment
@FUZxxl Это правда, что невозможно узнать, какие значения нераспределены, но диапазон типа int достаточно велик, чтобы обеспечить безопасный запас. Что касается конфликтов, я не вижу конфликтов, учитывая, что значение errno имеет только область действия одного вызова функции, поэтому, в зависимости от библиотеки, ошибка должна обрабатываться только по списку ошибок библиотеки, избегая конфликтов. Вы согласны? - person Felipe Lavratti; 30.10.2014
comment
@fani Я не согласен, потому что использование errno для нестандартных вещей нарушает такие вещи, как strerror - настраиваемое значение errno остается после неудачного вызова библиотеки и потенциально может испортить внешнюю обработку. - person fuz; 30.10.2014