metrica
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
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
Ваше сообщение отправлено.

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


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

Вебинар: Трудности при интеграции SAST, как с ними справляться - 04.04

>
>
>
V560. Part of conditional expression is…
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#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V560. Part of conditional expression is always true/false.

02 Дек 2021

Анализатор обнаружил потенциально возможную ошибку внутри логического условия. Часть логического выражения всегда истинно и оценено как опасное.

Рассмотрим пример:

#define REO_INPLACEACTIVE (0x02000000L)
...
if (reObj.dwFlags && REO_INPLACEACTIVE)
  m_pRichEditOle->InPlaceDeactivate();

Программист хотел проверить состояние определенного бита в переменной dwFlags. Но из-за опечатки он написал оператор '&&', вместо оператора '&'. Корректный код:

if (reObj.dwFlags & REO_INPLACEACTIVE)
  m_pRichEditOle->InPlaceDeactivate();

Рассмотрим другой пример:

if (a = 10 || a == 20)

Случайно вместо оператора сравнения '==' написан оператор присваивания '='. С точки зрения языка Си++, это выражение будет идентично выражению вида "if (a = (10 || a == 20))".

Выражение "10 || a == 20" анализатор считает опасным, так как левая его часть представляет собой константу. Корректный код:

if (a == 10 || a == 20)

Иногда предупреждение V560 выявляет не ошибку, а просто избыточный код. Рассмотрим пример:

if (!mainmenu) {
  if (freeze || winfreeze ||
      (mainmenu && gameon) ||
      (!gameon && gamestarted))
    drawmode = normalmode;
}

Анализатор предупредит, что в подвыражении (mainmenu && gameon) переменная mainmenu всегда равна 0. То, что переменная mainmenu равна нулю, следует из вышестоящей проверки " if (!mainmenu)". Этот код может быть вполне корректен. Однако он избыточен, и лучше его упростить. Это сделает программу более простой для понимания другими разработчиками.

Упрощенный вариант кода:

if (!mainmenu) {
  if (freeze || winfreeze ||
      (!gameon && gamestarted))
    drawmode = normalmode;
}

Рассмотрим более интересный случай.

int16u Integer = ReadInt16u(Liste);
int32u Exponent=(Integer>>10) & 0xFF;
if (Exponent==0 || Exponent==0xFF)  // V560
  return 0;

Пользователь, приславший этот пример, был озадачен, почему анализатор выдаёт предупреждение, в котором утверждается, что подвыражение 'Exponent==0xFF' всегда ложное. Давайте разберемся. Для этого нам надо внимательно посчитать.

16-битная беззнаковая переменная 'Integer' имеет диапазон возможных значений [0..0b1111111111111111] или [0..0xFFFF].

При сдвиге вправо на 10 бит, диапазон возможных значений уменьшается: [0..0b111111] или [0..0x3F].

Далее выполняется операция '& 0xFF'.

В результате, никак невозможно получить значение '0xFF'. Максимум, это будет '0x3F'.

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

  • подвыражение содержит операторы sizeof(): if (a == b && sizeof(T) < sizeof(__int64)) {};
  • выражение находится в макросе: assert(false);
  • сравниваются две числовых константы: if (MY_DEFINE_BITS_COUNT == 4) {};
  • и так далее.

Особые настройки диагностики V560

По дополнительной просьбе пользователей появилась возможность управлять поведением диагностики V560. В общем заголовочном файле или pvsconfig-файле можно написать комментарий специального вида:

//+V560 ENABLE_PEDANTIC_WARNINGS

Режим 'ENABLE_PEDANTIC_WARNINGS' ослабляет исключения диагностики. Рассмотрим пример:

void foo()
{
  bool debugCheck = false; // maybe in macros
  if (x)
  {
    if (debugCheck)
    {
      ....
    }
  }
}

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

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

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V560.