Книга: Основы программирования в Linux
Проверки соблюдения условий
Проверки соблюдения условий
Несмотря на то, что вставка на этапе разработки программы с помощью условной компиляции отладочного кода, такого как вызовы printf
, распространена, иногда оставлять такие сообщения в поставляемой программе непрактично. Но часто проблемы возникают во время работы программы из-за некорректных допущений или исходных данных, а не из-за ошибок кодирования. Это события, которых "не может быть никогда". Например, функция может быть написана в расчете на то, что ее входные параметры будут в определенном диапазоне. Если передать ей некорректные данные, она может сделать некорректной работу всей системы.
В тех случаях, когда внутренняя логика системы нуждается в подкреплении, X/Open предоставляет макрос assert
, применяемый для проверки правильности исходных данных и остановки выполнения программы в противном случае.
#include <assert.h>
void assert(int expression)
Макрос assert
вычисляет выражение и, если оно не равно нулю, выводит некоторую диагностическую информацию о стандартной ошибке и вызывает функцию abort
для завершения программы.
Заголовочный файл assert.h определяет макросы в зависимости от определения флага NDEBUG
. Если NDEBUG
определен во время обработки заголовочного файла, assert
определяется по существу как ничто. Это означает, что вы можете отключить проверки заданных выражений во время компиляции, компилируя с опцией -DNDEBUG
или вставив перед включением файла assert.h строку
#define NDEBUG
в каждый исходный файл.
Этот метод применения порождает проблему. Если вы используете assert
во время тестирования, но отключите макрос в рабочем коде, в вашем рабочем коде может оказаться менее строгая проверка, чем применявшаяся в процессе его тестирования. Обычно макросы assert
не оставляют включенными в рабочем коде — вряд ли вам понравится рабочий код, предоставляющий пользователю недружелюбное сообщение assert failed
и останавливающий программу. Быть может, лучше написать свою отслеживающую ошибки подпрограмму, которая проверяет выражение, использовавшееся в макросе, но не нуждается в полном отключении в рабочем коде.
Вы также должны убедиться в том, что у выражения макроса assert
нет побочных эффектов. Например, если вы применяете вызов функции с побочным эффектом, этот побочный эффект не проявится в рабочем коде с отключенными макросами assert
.
Выполните упражнение 10.2.
Упражнение 10.2. Программа assert.c.
Далее приведена программа assert.c, определяющая функцию, которая должна принимать положительное значение. Она защищает от ввода некорректного аргумента благодаря применению макроса assert
.
После включения заголовочного файла assert.h и функции "квадратный корень", проверяющей положительное значение параметра, вы можете писать функцию main
.
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <stdlib.h>
double my_sqrt(double x) {
assert(x >= 0.0);
return sqrt(x);
}
int main() {
printf("sqrt +2 = %gn", my_sqrt(2.0));
printf("sqrt -2 = %gn", my_sqrt(-2.0));
exit(0);
}
Теперь при выполнении программы вы увидите нарушение в макросе assert
при передаче некорректного значения. Точный формат сообщения о нарушении условия макроса assert в разных системах разный.
$ сс -о assert assert.с -lm
$ ./assert
sqrt +2 = 1.41421
assert: assert.c:7: my_sqrt: Assertion 'x >= 0.0' failed.
Aborted
$
Как это работает
Когда вы попытаетесь вызвать функцию my_sqrt
с отрицательным числом, макрос assert
даст сбой. Он предоставляет файл и номер строки, в которой нарушено условие и само нарушенное условие. Программа завершается прерыванием abort
. Это результат вызова abort
макросом assert
.
Если вы перекомпилируете программу с опцией -DNDEBUG
, макрос assert
не компилируется, и вы получаете NaN
(Not a Number, не число) — значение, указывающее на неверный результат при вызове функции sqrt
из функции my_sqrt
.
$ cc -о assert -DNDEBUG assert.с -lm
$ ./assert
sqrt +2 = 1.41421
sqrt -2 = nan
$
Некоторые более старые версии математической библиотеки генерируют исключение для математической ошибки, и ваша программа будет остановлена с сообщением "Floating point exception" ("Исключение для числа с плавающей точкой") вместо возврата NaN.
- Улучшенная стратегия вычисления предиката IN и условий, объединенных по OR
- 5. Null-значения и проверка условий
- 7.2. Операции проверки файлов
- Изменение условий
- 12.1. Операторы проверки: assert()
- Модель переменных условий и свойства безопасности
- Модель переменных условий
- Как проводить обсуждение технических условий
- Вопросы для самопроверки
- Приложение № 1. Чек-лист для проверки продающей страницы
- Приложение 15 Образец Особых условий к договору поставки
- Утверждения не являются механизмом проверки вводимых данных