Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

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

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

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

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

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

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


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

>
>
>
V719. The switch statement does not cov…
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Диагностика микро-оптимизаций (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Cтандарт MISRA
Стандарт AUTOSAR
Дополнительная информация
Оглавление

V719. The switch statement does not cover all values of the enum.

05 Мар 2015

Анализатор обнаружил подозрительный оператор 'switch'. Выбор варианта осуществляется по переменной enum-типа. При этом рассмотрены не все возможные варианты.

Поясним это на примере:

enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
}

Перечисление TEnum содержит 6 именованных констант. Но в операторе 'switch' используется только 5 из них. Высока вероятность, что это ошибка.

Такая ошибка часто возникает в ходе рефакторинга. В 'TEnum' добавили константу 'F". После этого какие-то 'switch' поправили, а про какие-то забыли. В результате, значение 'F' начинает обрабатываться неправильно.

Анализатор предупредит о том, что константа 'F' не используется. И тогда программист может исправить оплошность:

switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  case F: Y(66); break;
}

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

  • Есть default-ветка;
  • В перечислении всего 1 или 2 константы;
  • В switch не используется более чем 4 константы;
  • Отсутствующая константа содержит в имени: None, Unknown и т.п.
  • Отсутствующая константа самая последняя в enum и содержит в имени "end", "num", "count" и т.п.

Пользователь может сам задать список имён, которые обозначают последний элемент в перечислении. В этом случае анализатор не использует список имён по умолчанию, такие как "num" или "count". Будут использованы только имена, указанные пользователем. Комментарий, управляющий поведением диагностики V719:

//-V719_COUNT_NAME=ABCD,FOO

Вы можете разметить этот комментарий в одном из файлов, включаемый во все другие. Например, в StdAfx.h.

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

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

enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  default:
    throw MyException("Ай! Забыли рассмотреть один из вариантов!");
}

Ошибка может быть обнаружена только на этапе исполнения. Естественно есть желание отловить эту ситуацию и с помощью анализатора. В наиболее ответственных местах кода можно поступить следующим образом:

enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  #ifndef PVS_STUDIO
  default:
    throw MyException("Ай! Забыли рассмотреть один из вариантов!");
  #endif
}

Используется предопределённый макрос PVS_STUDIO. Этот макрос отсутствует при компиляции. Поэтому при компиляции исполняемого файла ветка 'default' остается на своём месте и в случае ошибки возникнет исключение.

При проверке кода с помощью PVS-Studio макрос PVS_STUDIO определён и поэтому анализатор не увидит default-ветку. Поэтому он проверит 'switch', обнаружит что не используется константа 'F' и выдаст предупреждение.

Исправленный вариант кода:

switch (x)
{
  case A: Y(11); break;
  case B: Y(22); break;
  case C: Y(33); break;
  case D: Y(44); break;
  case E: Y(55); break;
  case F: Y(66); break;
  #ifndef PVS_STUDIO
  default:
    throw MyException("Ай! Забыли рассмотреть один из вариантов!");
  #endif
}

Описанный подход не очень красив. Однако, если вы очень переживаете за какой-то 'switch' и хотите максимально защитить его, то этот способ вполне подходит.

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

  • CERT-MSC01-C

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

Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять