Чтение онлайн

на главную - закладки

Жанры

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

В Linux есть ряд других функций, предназначенных для генерирования временных файлов или их имен, в частности

mktemp
,
tmpnam
и
tempnam
. Работать с ними нежелательно, поскольку возникают упоминавшиеся выше проблемы, связанные с надежностью и безопасностью.

2.2. Защита от ошибок

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

В представленные ниже фрагменты программ сознательно не включены громоздкие коды проверки ошибок и восстановления после них. так как это привело бы к потере наглядности при рассмотрении основных методик. Тем не менее мы вернемся к данной теме в главе 11, "Демонстрационное Linux-приложение", где будут приведены полностью работающие программы.

2.2.1. Макрос assert

При написании программы следует помнить о том, что ошибки и непредвиденные ситуации могут радикально менять работу программы на самых ранних стадиях ее выполнения. Нужно стараться выявлять такие ошибки как можно раньше, на этапах разработки и отладки. Остальные ошибки, влияние которых на работу программы незначительно, обычно остаются незамеченными до тех пор, пока пользователи не начнут запускать программу.

Простейший способ выявления ненормальных ситуаций — стандартный макрос

assert
в языке С. Его аргументом является булево выражение. Программа завершается, если выражение оказывается ложным, при этом выводится сообщение об ошибке с указанием исходного файла и номера строки, а также текста выражения, приведшего к ошибке. Макрос
assert
оказывается очень полезным для самых разных проверок целостности, выполняемых внутри программы. Например, с помощью этого макроса проверяют правильность аргументов функций, выполнение входных и выходных условий при вызове функций (а также методов C++) и наличие непредвиденных возвращаемых значений.

Каждый вызов макроса

assert
является не только проверкой, осуществляемой на этапе выполнения, но и документацией, описывающей работу программы непосредственно в ее исходном тексте. Когда программа содержит строку assert (условие), то любой, кто читает исходный текст, будет знать, что в данной точке программы указанное условие всегда должно быть истинным. Если же условие не выполняется, то, очевидно, в программе присутствует ошибка.

В программах, критических к требованиям производительности, проверки

assert
на этапе выполнения могут представлять собой слишком большую нагрузку. В таких случаях программа компилируется с установленной макроконстантой
NDEBUG
; для этого в командной строке компилятора указывается флаг
– DNDEBUG
. При наличии данной макроконстанты препроцессор убирает из тела программы все вызовы макроса
assert
. И все же помните: делать это имеет смысл только тогда, когда производительность является узким местом программы, причем макрос нужно отключать лишь в наиболее критических файлах.

В связи с тем что макрос

assert
может удаляться препроцессором из программы, необходимо тщательно проверить, не имеют ли выражения с макросом побочных эффектов. В частности, в этих выражениях не следует вызывать функции, присваивать значения переменным и пользоваться модифицирующими операторами наподобие
++
.

Предположим, к примеру, что в цикле вызывается функция

do_something
. В случае успешного выполнения она возвращает 0, иначе — ненулевое значение. Легкомысленный программист считает, что функция всегда завершается успешно, поэтому возникает соблазн написать так:

for (i =0; i < 100; ++i)

 assert(do_something == 0);

Позднее, забыв о данной особенности, программист решает, что проверки на этапе выполнения заметно снижают производительность программы и нужно перекомпилировать программу с включенной макроконстантой

NDEBUG
. В результате из программы будут удалены все макросы
assert
, и функция
do_something
вообще не будет вызвана. На самом деле необходимо использовать следующий подход:

for (i = 0; i < 100; ++i) {

 int status = do_something;

 assert(status == 0);

}

Еще один важный момент: макрос

assert
не следует применять для проверки данных, вводимых пользователем. Пользователи не любят, когда программа аварийно завершает свою работу, выдавая малопонятное сообщение об ошибке, даже если причиной этого стали неправильно введенные данные. Конечно, входные данные всегда нужно проверять, но другими способами. Макрос
assert
предназначен лишь для внутренних проверок.

Дадим несколько полезных советов.

■ Проверяйте наличие пустых указателей, например в списке аргументов функции. Сообщение об ошибке, генерируемое строкой

{assert (pointer != NULL)}
,

Assertion 'pointer != ((void *)0)' failed.

более информативно, чем сообщение, выдаваемое в ответ на попытку раскрытия пустого указателя:

Segmentation fault (core dumped)

■ Проверяйте значения параметров функции. Например, если в функции предполагается, что параметр

foo
имеет только положительные значения, поставьте следующую проверку в самом начале тела функции:

assert(foo > 0);

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

2.2.2. Ошибки системных вызовов

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

Реалии развития компьютерных систем разрушили этот идеал. Ресурсы компьютеров ограничены; иногда происходят аппаратные сбои; многие программы выполняются одновременно; пользователи и программисты делают ошибки. Часто все это проявляется на границе между приложением и операционной системой. Следовательно, используя системные вызовы для доступа к ресурсам, осуществления операций ввода-вывода или других целей, нужно понимать не только то, что именно происходит при успешном завершении вызова, но также при каких обстоятельствах он может завершиться неуспешно.

Поделиться:
Популярные книги

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Варвара Асенкова

Алянский Юрий Лазаревич
Корифеи русской и зарубежной сцены
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Варвара Асенкова

Дитя прибоя

Трофимов Ерофей
Дитя прибоя
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Дитя прибоя

Царь царей

Билик Дмитрий Александрович
9. Бедовый
Фантастика:
фэнтези
мистика
5.00
рейтинг книги
Царь царей

На границе империй. Том 10. Часть 5

INDIGO
23. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 5

Избрание сочинения в трех томах. Том второй

Кочетов Всеволод Анисимович
Проза:
советская классическая проза
5.00
рейтинг книги
Избрание сочинения в трех томах. Том второй

Законы Рода. Том 9

Мельник Андрей
9. Граф Берестьев
Фантастика:
городское фэнтези
попаданцы
аниме
дорама
фэнтези
фантастика: прочее
5.00
рейтинг книги
Законы Рода. Том 9

Афганский рубеж

Дорин Михаил
1. Рубеж
Фантастика:
попаданцы
альтернативная история
7.50
рейтинг книги
Афганский рубеж

Воин

Бубела Олег Николаевич
2. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.25
рейтинг книги
Воин

Граф Книга третья

Первухин Андрей Евгеньевич
10. Ученик
Фантастика:
фэнтези
попаданцы
5.25
рейтинг книги
Граф Книга третья

Второгодка. Книга 5. Презренный металл

Ромов Дмитрий
5. Второгодка
Фантастика:
городское фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Второгодка. Книга 5. Презренный металл

Матабар

Клеванский Кирилл Сергеевич
1. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар

Воронцов. Перезагрузка. Книга 2

Тарасов Ник
2. Воронцов. Перезагрузка
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Воронцов. Перезагрузка. Книга 2

Чужак из ниоткуда 2

Евтушенко Алексей Анатольевич
2. Чужак из ниоткуда
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Чужак из ниоткуда 2