Следует ли избегать последовательных звонков в `errno`? - PullRequest
7 голосов
/ 06 октября 2010

Безопасно ли звонить errno несколько раз, когда происходит одна и та же ошибка. Или безопаснее работать с локальной копией?

Этот пример иллюстрирует мой вопрос:

// If recvfrom() fails it returns -1 and sets errno to indicate the error.
int res = recvfrom(...);
if (res < 0)
{
    // Risky?
    printf("Error code: %d. Error message: %s\n", errno, strerror(errno));

    // Safer alternative?
    int errorNumber = errno;
    printf("Error code: %d. Error message: %s\n", errorNumber, strerror(errorNumber));
}

Ответы [ 5 ]

5 голосов
/ 06 октября 2010

Значение errno должно быть определено только после вызова функции, для которой оно явно указано для установки, и до тех пор, пока оно не будет изменено при следующем вызове функции или если приложение присвоит ему значение.

http://www.opengroup.org/onlinepubs/009695399/functions/errno.html

Тем не менее, даже strerror теоретически может считаться вызовом функции, который может изменить его (см. Комментарий по schot), поэтому теоретически вы должны продолжать использовать форму сохранения вначале.

2 голосов
/ 06 октября 2010

Любая стандартная библиотечная функция, включая printf и strerror, может изменять значение errno, даже если на самом деле ошибки не возникает:

7.5 3 Значение errno равно нулю при запуске программы, но никогда не устанавливается в ноль какой-либо библиотечной функцией.170) Значение errno может быть установлено на ненулевое значение при вызове библиотечной функции независимо от того, есть ли ошибка, при условии, что использование errno не задокументировано в описании функции в этом международном стандарте.

1 голос
/ 06 октября 2010

Обычно в наши дни errno - это нечто гораздо более сложное, чем переменная:

... ошибка, которая расширяется до модифицируемое lvalue, которое имеет тип int, значение которого установлено в положительное число ошибок на несколько библиотечные функции. Не указано является ли errno макросом или идентификатор объявлен с внешним связь. Если определение макроса подавлено для того, чтобы получить доступ к фактический объект, или программа определяет идентификатор с именем errno, поведение не определено.

например. в POSIX гарантированно что-то определенное для текущего потока. Таким образом, он может иметь стоимость доступа выше, чем для простой переменной.

Так что да, я бы пошел на локальную копию, если производительность вызывает проблемы, хотя я никогда не проверял это по-настоящему.

1 голос
/ 06 октября 2010

errno является переменной и не функцией.Когда вы используете его, он не может быть сброшен.Таким образом, можно использовать число ошибок errno несколько раз, при условии, что вы не вызываете функцию, которая может изменить / сбросить errno.

0 голосов
/ 11 сентября 2015

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

char **str_array = (char**) malloc(SOME_CONSTANT * sizeof(char*));
if (str_array == NULL){
    perror("malloc failed on str_array");
}

perror печатает введенную строку, добавляет пробел,точка с запятой, а затем печатает читаемый человеком текст ошибки.Похоже, что он также не имеет побочного эффекта, который делает strerror, если я неправильно интерпретирую man-страницу, потому что в ней нет раздела для ОШИБК: http://man7.org/linux/man-pages/man3/perror.3.html.

I 'Я также делаю последовательные вызовы, которые могут быть неудачными, и perror выглядит как меньшее количество строк кода и лучший синтаксис.Тем не менее, я новичок в C, поэтому, пожалуйста, измените или удалите, если эта информация неточна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...