return Success;
}
Обратите внимание, что при вычислении возвращаемого функцией значения булевской переменной Success, которое служит индикатором успешности выполнения, в программе, с выгодой для логики ее работы, используется тот факт, что стандартом ANSI С гарантируется так называемое "сокращенное" вычисление логических выражений в направлении слева направо; поэтому, как только при вычислении части выражения, расположенной слева от любой из операций логического "и" (&&), в качестве результата будет получено значение FALSE, остальная часть выражения, расположенная справа от данной операции, вычисляться не будет, поскольку результат вычисления всего выражения в целом оказывается предопределенным. Данный стиль написания программ может показаться чересчур компактным, однако он обладает тем преимуществом, что позволяет организовать логически стройную и понятную последовательность системных вызовов, не загромождая программу многочисленными операторами условных переходов. Для получения более подробной информации о возможных ошибках можно воспользоваться функцией GetLastError. Распространенный в Windows возврат функциями логических значений поощряет подобную практику.
В данной функции сообщения об ошибках не выводятся; их вывод, если это будет необходимо, можно предусмотреть в вызывающей программе.
В программном коде используется тот документированный факт, что при использовании функции WriteConsole вместе с дескриптором, который не является дескриптором консоли, ее выполнение будет завершено с ошибкой. В связи с этим предварительный запрос свойств дескриптора не является обязательным. Функция воспользуется консольным режимом лишь в том случае, если указанный в ее вызове дескриптор действительно связан с консолью.
Кроме того, функция ReadConsole возвращает управляющие символы возврата каретки и перехода на новую строку, что диктует необходимость вставки дополнительных нулевых символов после символов возврата каретки в соответствующих местах.
Пример: обработка ошибок
В программе 1.2 было продемонстрировано использование лишь самых примитивных средств обработки ошибок, а именно, получение номера ошибки в переменной типа DWORD с помощью функции GetLastError. Вызов функции, а не просто получение глобального номера ошибки, как это делается при помощи функции UNIX errno, гарантирует уникальную идентификацию системных ошибок для каждого из потоков (глава 7), использующих разделяемую область хранения данных.
Функция FormatMessage превращает простой номер сообщения в описательное сообщение, представляющее собой фразу на английском или любом другом из множества возможных языков, и возвращает размер сообщения.
В программе 2.2 представлена полезная универсальная функция ReportError, предназначенная для обработки ошибок и по своим возможностям аналогичная входящей в состав библиотеки С функции perror, а также описанным в [40] функциям err_sys и err_ret. Функция ReportError передает в выходной буфер сообщение в виде, определяемом первым аргументом, и либо прекращает выполнение с кодом выхода по ошибке, либо осуществляет обычный возврат управления, в зависимости от значения второго аргумента. Третий аргумент определяет, должны ли отображаться системные сообщения об ошибках.
Обратите внимание на аргументы функции FormatMessage. В качестве одного из параметров используется значение, возвращаемое функцией GetLastError, a на необходимость генерации сообщения системой указывает флаг. Сгенерированное сообщение сохраняется в буфере, выделяемом функцией, а соответствующий адрес возвращается в параметре. Имеются также другие параметры, для которых указаны значения по умолчанию. Язык сообщений может быть задан как во время компиляции, так и во время выполнения. В этой книге функция Format-Message далее нигде не используется, поэтому никаких дополнительных пояснений относительно нее в тексте не дается.
Функция ReportError упрощает обработку ошибок, и будет использоваться почти во всех последующих примерах. В главе 4 она будет модифицирована для генерации исключений.
В программе 2.2 вводится заголовочный файл EvryThng.h. Как следует из самого его названия, этот файл включает в себя файлы
Обратите внимание на вызов функции HeapFree, находящийся почти в конце программы. Об этой функции будет рассказано в главе 5.