2013-08-21 1 views
5

Я пишу программу, в которой большинство используемых функций библиотеки return -1 при ошибке и установить errno. Поведение программы таково, что она выходит, если возникает ошибка. Для того, чтобы определить точную точку выхода и ошибки из-за программы (например, с помощью gdb), я хочу использовать следующий метод:Можно ли предположить, что errno всегда будет положительным?

err = func_1(..arglist_1..); 
if(err != 0) 
{ 
    perror("func(..arglist..)"); 
    return ((1u << 8) | errno); 
} 
//.. 
//.. some more funcs 
//.. 
err = func_n(..arglist_n..); 
if(err != 0) 
{ 
    perror("func(..arglist_n..)"); 
    return (((unsigned)n << 8) | errno); 
} 

Проблема здесь безопасные предположения.

Действительность:ERRNO объявлен как extern int errno; внутри errno.h
Предположение 1: Значение ERRNO всегда меньше 255.
Предположение 2:ERRNO всегда положительна.

На основании всех констант ошибок (EAGAIN и т. Д.), Определенных в errno.h, эти предположения в настоящее время верны. Могут ли они считаться истинными и в будущем?

P.S .: Я не хочу зависеть от perror(), чтобы определить точку выхода.

+0

Сомневаюсь, что любое предположение безопасно. Для второго, считаете ли вы «0» положительным? – jxh

+0

Отсутствует '0', поскольку [эта ссылка здесь] (http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html) говорит:' Никакая функция в этом томе IEEE Std 1003.1-2001 не будет установлена errno to 0.' –

+2

Просто потому, что никакая функция в стандартной библиотеке не устанавливает ее в '0', не означает, что кто-то другой не устанавливает ее в' 0'. Для некоторых стандартных функций библиотеки единственный способ определить, был ли сбой вызова, - это сначала установить 'errno' в' 0', а затем посмотреть, что делает функция. – jxh

ответ

12

Статус выхода вашей программы ограничен 0..255, поэтому, если эти операторы return из программы main(), биты верхнего порядка не имеют значения.

Стандарт С (ISO/IEC 9899: 2011 §7.5 Ошибки <errno.h>) говорит:

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

201) Макрос errno не обязательно должен быть идентификатором объекта. Он может расширяться до изменяемого значения , вызванного вызовом функции (например, *errno()).

Стандарт C ожидает, что ошибки будут положительными. POSIX (IEEE Std 1003.1, 2013 Edition) состояний для <errno.h>:

Заголовок <errno.h> определяет следующие макросы, которые должны расширить до целых константных выражений с типом int, различные положительные значения (за исключением случаев, указанных ниже), и который должен быть пригодна для использования в #if директивах препроцессора: ...

Таким образом, вы можете достаточно смело предположить, что (сгенерированную систему) число ошибок являются положительным, но ваш код может установить errno отрицательные (или ноль). На данный момент ни одна система POSIX не генерирует числа ошибок выше, чем где-то менее 200, поэтому, если предположить, что они будут ограничены 255, это будет безопасным в краткосрочной перспективе, но, вероятно, не в долгосрочной перспективе. Нет причин, по которым они должны быть настолько ограниченными.

Ваша заявленная «реальность» применима только к не-потоковым программам. Если вы компилируете для поддержки с резьбой, то errno не просто объявляется как extern int errno; и ни при каких обстоятельствах не следует пытаться объявить errno для себя. только безопасный способ объявить это через заголовок <errno.h>.

+0

Хорошо, я получил свой ответ, спасибо Джонатан Леффлер. Прежде всего, он прав, я намеревался сделать это в основном(). Затем, моя ошибка, я забыл о многопоточных программах. Кроме того, я использовал [старую копию стандарта] (http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html) для справки, там не упоминается, что он всегда будет положительным. –

+1

C89 не предусматривал, что номера ошибок были положительными (просто отличными от нуля); В C99 было указано, что числа ошибок были положительными. Интересно, что POSIX 1997 сказал: «Заголовок' 'предоставляет объявление для errno и дает ненулевые значения для следующих символических констант». что согласуется с тогдашним токовым C89 (C90) стандартом. –

+0

@nishant: интересно - вы связались с страницей POSIX 2004 для 'errno', которая не упоминает« положительный »(и страница POSIX 2013 для [' errno'] (http: //pubs.opengroup. org/onlinepubs/9699919799/functions/errno.html)), тогда как я связан с страницей POSIX (2013) для '', что упоминает об этом (как и страница POSIX 2004 для заголовка). Наверное, мне посчастливилось выбрать подходящее место для поиска; Я не знал об асимметрии. –

Смежные вопросы