Тестирование `errno` после вызова `strtol` возвращает Нет такого процесса

Несмотря на успешное преобразование строки, проверка errnoвозвращает значение, указывающее на ошибку:

#include <stdlib.h>
#include <sys/errno.h>

const char* numberString = "7";
char* endPtr;
errno = 0;
long number = strtol(numberString, &endPtr, 10);
NSLog(@"%ld", number);
if (errno) {
    perror("string to integer conversion failed");
}

Выход есть (на Симуляторе, iOS 7)

$ 2014-05-22 09:27:32.954 Test[2144:60b] 7
$ string to integer conversion failed: No such process

На устройстве поведение аналогичное.

справочная страница для strtol говорит в комментарии:

ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ
Функции strtol(), strtoll(), strtoimax() и strtoq() возвращают результат преобразования, если только значение не будет переполнено или потеряно. Если преобразование не может быть выполнено, возвращается 0, а глобальная переменная errno устанавливается в EINVAL (последняя функция не переносима на все платформы). Если происходит переполнение или потеря значимости, для errno устанавливается значение ERANGE, а возвращаемое значение функции фиксируется в соответствии со следующей таблицей.

Совершенно неясно, что именно это означает для iOS. Любые идеи здесь?

Редактировать:

Оказалось, что вызов функции NSLog установил errno. Итак, @Mat в своем ответе и комментариях был точен, говоря, что «все ставки сняты при тестировании errno ПОСЛЕ вызова несвязанной функции (здесь NSLog).


person CouchDeveloper    schedule 22.05.2014    source источник
comment
Похоже, что errno устанавливается только в том случае, если strtol терпит неудачу - поскольку strtol завершается успешно, вам не следует пытаться прочитать errno.   -  person Paul R    schedule 22.05.2014


Ответы (1)


Если преобразование не может быть выполнено, возвращается 0

Ты не в том случае, 7 вернули.

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

Вы тоже не в этом случае.

Так что strtol не подвел. Проверка errno бессмысленна. Функция, которая задокументирована для установки errno при сбое, сделает это в случае сбоя. Если сбоев не произошло, значение errno «морально» не определено. Не проверяйте это.

Однако strtol — это особый случай. POSIX требует следующего:

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

Так что ваш пример должен быть в порядке. За исключением того, что вы вызываете функцию между вызовом strtol и проверкой errno. Если вы на 100 % уверены, что эта функция сама не изменит errno или не вызовет другую функцию, которая может ее установить, тогда все будет в порядке в этом очень конкретном случае (функция, документально подтвержденная, чтобы не изменять errno в случае успеха — это это не норма). Хотя видимо это не так. NSLog, скорее всего, в какой-то момент будет использовать некоторые системные вызовы, и у них (в общем) нет гарантии, что они не изменят errno.

person Mat    schedule 22.05.2014
comment
Это имеет смысл. Кстати, на cppreference.com есть пример, который кажется неверным, как и мой образец: пример strtol - person CouchDeveloper; 22.05.2014
comment
Гум. Странно, обычно это отличная отсылка. Позвольте мне проверить, не пропустил ли я что-то здесь. - person Mat; 22.05.2014
comment
@CouchDeveloper: да, извините, мой ответ был неправильным. Я считаю, что сейчас это так, и общий совет действительно применим - не проверяйте errno в случае успеха и проверяйте errno сразу после неудачного вызова. Этот пример в cppreference должен сбросить errno до нуля непосредственно перед вызовом strol в цикле, чтобы он был действительным, если только я не упустил что-то еще: -/ - person Mat; 22.05.2014
comment
Спасибо за обновления. Обратите внимание, что я тоже установил errno на ноль перед вызовом strtol. И несмотря на то, что strtol не должен касаться errno, так как это удается, он возвращает ESRCH (такого процесса нет). ESRCH даже не указан как один из возможных кодов ошибок для strtol на странице руководства. - person CouchDeveloper; 22.05.2014
comment
@CouchDeveloper: вы вызываете функцию между strtol и проверкой ошибки. Все ставки сделаны. - person Mat; 22.05.2014
comment
Мат, ты был абсолютно прав! Функция NSLog на самом деле установила errno! Странно, но это так. Спасибо за помощь. :) - person CouchDeveloper; 22.05.2014