В любой реальной программе существенным моментом является проверка каждого вызова функции на предмет возвращаемой ошибки. В листинге 1.1 мы проводим поиск ошибок в вызовах функций >socket
, >inet_pton
, >connect
, >read
и >fputs
, и когда ошибка случается, мы вызываем свои собственные функции >err_quit
и >err_sys
для печати сообщения об ошибке и для прерывания выполнения программы. В отдельных случаях, когда функция возвращает ошибку, бывает нужно сделать еще что-либо помимо прерывания программы, как показано в листинге 5.9, когда мы должны проверить прерванный системный вызов.
Поскольку прерывание программы из-за ошибки — типичное явление, мы сократим наши программы, определив функции-обертки, которые будут вызывать соответствующие рабочие функции, проверять возвращаемые значения и прерывать программу при возникновении ошибки. Соглашение, используемое нами, заключается в том, что название функции-обертки пишется с заглавной буквы, например:
>sockfd = Socket(AF_INET, SOCK_STREAM, 0);
Наша функция-обертка для функции socket показана в листинге 1.3.
Листинг 1.3. Наша функция-обертка для функции socket
>//lib/wrapsock.c
>172 int
>173 Socket(int family, int type, int protocol)
>174 {
>175 int n;
>176 if ((n = socket(family, type, protocol)) < 0)
>177 err_sys("socket error");
>178 return (n);
>179 }
Хотя вы можете решить, что использование этих функций-оберток не обеспечивает большой экономии, на самом деле это не так. Обсуждая потоки (threads) в главе 26, мы обнаружим, что, когда происходит какая-либо ошибка, функции потоков не устанавливают значение стандартной переменной Unix >errno
равным определенной константе, специфической для произошедшей ошибки. Вместо этого значение переменной >errno
просто возвращается функцией. Это значит, что каждый раз, когда мы вызываем одну из функций >pthread
, мы должны разместить в памяти переменную, сохранить возвращаемое значение в этой переменной и установить >errno
равной этому значению перед вызовом >err_sys
. Чтобы избежать загромождения кода скобками, мы можем использовать оператор языка С запятая для объединения присваивания значения переменной >errno
и вызова >err_sys
в отдельное выражение следующим образом:
>int n;
>if ((n = pthread_mutex_lock(&ndone_mutex)) != 0)
> errno = n, err_sys("pthread_mutex_lock error");
ВНИМАНИЕ
В тексте книги вам будут встречаться функции, имена которые начинаются с заглавной буквы. Это наши собственные функции-обертки. Функция-обертка вызывает функцию, имеющую такое же имя, но начинающееся со строчной буквы.