Урок 109. Assert и static_assert

   ⁄ 

 Обновлено 23 Янв 2018  ⁄ 

⁄   1249

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

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

Сам assert реализован в заголовочном файле <cassert> и часто используется как для проверки корректности переданных параметров функции, так и для проверки возвращаемого значения функции.

Если в программе выше вызвать getArrayValue(array, -3);, то программа выведет следующее сообщение:

Assertion failed: index >= 0 && index <=8, file C:\\VCProjects\\Program.cpp, line 6

Мы рекомендуем использовать стейтменты assert.

Еще немного об assert

Иногда утверждения assert бывают не очень описательными. Например:

Если этот assert сработает, то получим:



Assertion failed: found, file C:\\VCProjects\\Program.cpp, line 42

Но что это нам сообщает? Очевидно, что что-то не было найдено, но что? Вам нужно будет самому пройтись по коду, чтобы это определить.

К счастью, есть небольшой трюк, который можно использовать для исправления этой ситуации. Просто добавьте сообщение в качестве строки C-style вместе с логическим оператором И:

Как это работает? Строка C-style всегда принимает значение true. Поэтому, если found примет значение false, то false && true = false. Если же found примет значение true, то true && true = true. Таким образом, строка C-style вообще не влияет на обработку утверждения.

Однако, если assert сработает, то строка C-style будет включена в сообщение assert:

Assertion failed: found && "Animal could not be found in database", file C:\\VCProjects\\Program.cpp, line 42

Это даст дополнительный контекст относительно того, что пошло не так.

NDEBUG

Функция assert() тратит мало ресурсов на проверку условия. Кроме того, утверждения должны (в идеале) никогда не встречаться в релизном коде (потому что ваш код к этому моменту уже должен быть тщательно протестирован). Следовательно, многие разработчики предпочитают использование assert только в режиме отладки. В C++ есть возможность отключить все assert-ы в релизном коде — использование #define NDEBUG:

Некоторые IDE устанавливают NDEBUG по умолчанию как часть параметров проекта в конфигурации Release.

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

static_assert

В C++11 добавили еще один тип assert-а — static_assert. Он выглядит следующим образом:

static_assert

В отличие от assert, который выполняется во время выполнения, static_assert выполняется во время компиляции, вызывая ошибку компилятора, если условие не является истинным. Если условие ложное, то выводится диагностическое сообщение.

Вот пример использования static_assert для проверки размеров определенных типов данных:

Результат на компьютере автора:

1>C:\ConsoleApplication1\main.cpp(19): error C2338: long must be 8 bytes



Поскольку static_assert обрабатывается компилятором, то условная часть static_assert должна также обрабатываться во время компиляции. Поскольку static_assert не обрабатывается во время выполнения, то стейтменты static_assert могут быть размещены в любом месте кода (даже в глобальном пространстве).

В C++11 диагностическое сообщение должно быть обязательно предоставлено в качестве второго параметра. В C++17 предоставление диагностического сообщения является необязательным.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (11 оценок, среднее: 5,00 из 5)
Загрузка...
Подписаться на обновления:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

ПОДПИСЫВАЙТЕСЬ

НА КАНАЛ RAVESLI В TELEGRAM

@ravesli

ПОДПИСАТЬСЯ БЕСПЛАТНО