Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V2021. Using assertions may cause the a…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V2021. Using assertions may cause the abnormal program termination in undesirable contexts.

31 Июл 2024

Данное диагностическое правило добавлено по просьбе пользователей.

Диагностическое правило позволяет обнаружить в коде вызов макроса, который может привести к аварийному завершению программы. Таким макросом может быть стандартный 'assert'. Несмотря на то, что его использование позволяет устранять ошибки и снизить вероятность возникновения уязвимостей, его вызов может быть недопустим в различных сценариях. Одним из таких вариантов может быть написание библиотечного кода.

Рассмотрим следующий код:

[[noreturn]] void assertHandler();
#define ASSERT(expr) (!!(expr) || (assertHandler(), 0))

void foo(int i)
{
  if (i < 0)
  {
    ASSERT(false && "The 'i' parameter must be non-negative");
  }
}

В примере приведена пользовательская реализация макроса 'assert', которая вызывает функцию, не возвращающую поток управления вызывающей функции. Требуется, чтобы анализатор выдал срабатывание на вызов этого макроса. Для этого надо внести небольшие изменения в код:

[[noreturn]] void assertHandler();                      // N1
#define ASSERT(expr) (!!(expr) || (assertHandler(), 0))

//V_PVS_ANNOTATIONS annotations.json                    // N2
//V_ASSERT_CONTRACT, assertMacro:ASSERT                 // N3

void foo(int i)
{
  if (i < 0)
  {
    ASSERT(false);                                      // <= V2021
  }
}

На этом примере рассмотрим, как настраивается механизм распознавания пользовательского макроса.

Разметка функции как noreturn. Функция 'assertHandler', расположенная внутри макроса 'ASSERT', должна быть размечена как 'noreturn' (строка N1). Это можно сделать как при помощи стандартных атрибутов (C23 и C++11):

[[noreturn]] void assertHandler();              // since C23 or C++11

Так и специфичными для компилятора атрибутами (например, MSVC или GCC / Clang):

__declspec(noreturn) void assertHandler();      // MSVC
__attribute__((noreturn)) void assertHandler(); // GCC, Clang

Если нет возможности изменить исходный код и разметить функцию атрибутом, то можно сделать это c помощью системы пользовательских аннотаций в формате JSON. Для этого нужно создать файл формата JSON со следующим содержимым:

{
  "version": 1,
  "annotations": 
  [
    {
      "type": "function",
      "name": "assertHandler",
      "parameters": [],
      "attributes": [ "noreturn" ]
    },
    ....
  ]
}

Затем этот файл должен быть включён во время анализа одним из описанных способов. В примере это происходит в строке N2.

Разметка макроса. Необходимо, чтобы анализатор учитывал, что из-за макроса 'ASSERT' выполнение кода может прерваться. Делается это при помощи комментария на строке N3. Более подробно об этом механизме можно узнать здесь.

Задание имён функций, в которых допустим вызов макроса

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

//-V2021_IGNORE_ASSERT_IN_FUNCTION, function: My::Qualified::Name

Примечание. Данная диагностическое правило срабатывает также и на стандартный 'assert', и поэтому отключено по умолчанию, чтобы не выдавать большое количество срабатываний.

Для того, чтобы включить диагностику, можно воспользоваться механизмом включения через комментарий или директивой '#pragma pvs'.

Данная диагностика классифицируется как:

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам