Урок №109. assert и static_assert

  Юрий  | 

  |

  Обновл. 13 Сен 2021  | 

 82008

 ǀ   4 

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

Стейтмент assert

Стейтмент assert (или «оператор проверочного утверждения») в языке C++ — это макрос препроцессора, который обрабатывает условное выражение во время выполнения. Если условное выражение истинно, то стейтмент 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 (в идеале) никогда не должны встречаться в релизном коде (потому что ваш код к этому моменту уже должен быть тщательно протестирован). Следовательно, многие разработчики предпочитают использовать 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 (336 оценок, среднее: 4,94 из 5)
Загрузка...

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

  1. Илья:

  2. Анастасия:

    В примере

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

    1. Евгений:

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

    2. Steindvart:

      Может быть булевой переменной. Или же каким-то объектом, значение которого можно неявно или явно преобразовать в true или false.

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

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