Несмотря на то, что вставка на этапе разработки программы с помощью условной компиляции отладочного кода, такого как вызовы printf
В тех случаях, когда внутренняя логика системы нуждается в подкреплении, X/Open предоставляет макрос assert
#include
void assert(int expression)
Макрос assert
abort для завершения программы.Заголовочный файл assert.h определяет макросы в зависимости от определения флага NDEBUG
NDEBUG определен во время обработки заголовочного файла, assert определяется по существу как ничто. Это означает, что вы можете отключить проверки заданных выражений во время компиляции, компилируя с опцией -DNDEBUG или вставив перед включением файла assert.h строку#define NDEBUG
в каждый исходный файл.
Этот метод применения порождает проблему. Если вы используете assert
assert не оставляют включенными в рабочем коде — вряд ли вам понравится рабочий код, предоставляющий пользователю недружелюбное сообщение assert failed и останавливающий программу. Быть может, лучше написать свою отслеживающую ошибки подпрограмму, которая проверяет выражение, использовавшееся в макросе, но не нуждается в полном отключении в рабочем коде.Вы также должны убедиться в том, что у выражения макроса assert
assert.Выполните упражнение 10.2.
Далее приведена программа assert.c, определяющая функцию, которая должна принимать положительное значение. Она защищает от ввода некорректного аргумента благодаря применению макроса assert
После включения заголовочного файла assert.h и функции "квадратный корень", проверяющей положительное значение параметра, вы можете писать функцию main
#include
#include
#include
#include
double my_sqrt(double x) {
assert(x >= 0.0);
return sqrt(x);
}
int main() {
printf("sqrt +2 = %g\n", my_sqrt(2.0));
printf("sqrt -2 = %g\n", my_sqrt(-2.0));
exit(0);
}
Теперь при выполнении программы вы увидите нарушение в макросе 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.
Устранение ошибок использования памяти
Распределение динамической памяти — богатый источник ошибок, которые трудно выявить. Если вы пишете программу, применяющую функции malloc
free для распределения памяти, важно внимательно следить за блоками, которые вы выделяете, и быть уверенным в том, что не используется блок, который вы уже освободили.