Урок №109. assert и static_assert

  Юрий  | 

    | 

  Обновл. 9 Июн 2019  | 

 11512

 ǀ   2 

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

Стейтмент 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 сработает, то получим:

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 только в конфигурации Debug. В C++ есть возможность отключить все assert-ы в релизном коде — использовать #define NDEBUG:

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

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

static_assert

В C++11 добавили ещё один тип 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 (79 оценок, среднее: 4,92 из 5)
Загрузка...

Комментариев: 2

  1. Аватар Анастасия:

    В примере

    found — это какая-то булева переменная? Или спец слово, используемое вместе с assert в каких-то не описанных здесь случаях?

    1. Аватар Евгений:

      булева переменная

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

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