Как стать автором
Поиск
Написать публикацию
Обновить
320.7
PVS-Studio
Статический анализ кода для C, C++, C# и Java

Безболезненное внедрение статического анализа и победа над ложными срабатываниями

Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров606

Поговорим о том, как механизм baseline может упростить внедрение статического анализатора в проект, а также о том, как бороться с ложноположительными срабатываниями.

Внедрение анализатора в проект и baseline

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

А теперь представьте, что мы сразу же возьмёмся размечать все эти срабатывания, а также исправлять найденные ошибки... Во-первых, мы потратим довольно много времени на это, а во-вторых, разоримся на психологах для разработчиков :)

Что же делать в таком случае?

Для начала мы должны понимать, что перед использованием статический анализатор нужно настраивать. В анализаторе PVS-Studio, например, сейчас более 1500 диагностических правил суммарно для четырёх языков. Понятное дело, что не все эти диагностики могут быть вам полезны.

Например, есть такая вещь, как стандарты MISRA для C и C++. В нашем анализаторе есть поддержка этих стандартов и соответствующие диагностические правила. MISRA отличается дотошностью в обеспечении безопасности и ругается на самые мелкие проблемы в коде, потому что стандарт изначально был создан для разработки программного обеспечения в области автомобильной промышленности, а сегодня используется в любой сфере, где стоимость ошибки невероятно высока. Поэтому если вы не пишете код в соответствии с этими стандартами, то всё, что вам дадут срабатывания MISRA диагностик, это лишний шум в отчёте.

Примечание. Если вам интересны стандарты MISRA, то у нас есть страница на сайте, посвящённая их поддержке в анализаторе PVS-Studio.

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

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

В статическом анализаторе PVS-Studio для таких случаев есть режим suppress, в котором анализатор сохраняет подавленные сообщения в так называемые suppress-файлы. Этот режим не требует внесения изменений в исходный код, а также удобен для массового подавления срабатываний. Анализатор сохраняет сигнатуру срабатывания, в том числе и исходный код, на который оно было выдано, чтобы в будущем без ведома пользователя срабатывание не вернулось в отчёт.

Как же подавить срабатывания анализатора? Например, в плагине PVS-Studio для интегрированной среды разработки Visual Studio есть специальная кнопка в меню просмотра отчёта, с помощью которой можно подавить все срабатывания анализатора:

После нажатия анализатор запишет все срабатывания в основной suppress-файл проекта, при этом они пропадут из окна просмотра отчёта.

Также есть возможность подавления конкретных срабатываний с помощью выпадающего меню:

Подобная функциональность присутствует во всех плагинах PVS-Studio для интегрированных сред разработки: IntelliJ IDEA, CLion, Rider, Visual Studio, Visual Studio Code и Qt Creator.

В плагине для Visual Studio с помощью специального меню Suppress Messages плагина можно посмотреть, какие срабатывания были подавлены:

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

Подавление ложноположительных срабатываний

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

Примечание. Иногда вместо борьбы с ложными срабатываниями лучшим решением будет просто отключить анализ конкретных файлов. Например, для автогенерируемых файлов анализатор может выдать много различных срабатываний, убрав которые, мы избавимся от лишнего шума в отчёте.

Подавить ложное срабатывание в анализаторе PVS-Studio можно с помощью специальных комментариев. Допустим, в таком фрагменте анализатор выдал срабатывание:

size_t n = 100;
for (unsigned i = 0;
     i < n;          // здесь получаем V104
     i++)
{
    // ...
}

Если мы уверены, что это срабатывание ошибочное и готовы убрать его из отчёта, необходимо добавить вот такой комментарий с номером диагностического правила:

size_t n = 100;
for (unsigned i = 0;
     i < n; //-V104
     i++)
{
    // ...
}

Если необходимо подавить срабатывания сразу нескольких диагностик на одну и ту же строку, то делается это столь же просто:

struct Small { int *pointer; };
struct Big { int *array[20]; };
int Add(const Small &a, Big b) //-V835 //-V813
{
  return *a.pointer + *b.array[10];
}

Также можно ставить дополнительный хэш-код к метке False Alarm. При изменении строки, в которой мы установим такой хэш-код, выданные на неё предупреждения анализатора не будут отмечены как ложные срабатывания, так как хэш-код изменённой строки будет отличаться от кода из метки.

Для включения этой функции необходимо добавить в файл конфигурации правил .pvsconfig следующий флаг:

//V_ENABLE_FALSE_ALARMS_WITH_HASH

В коде метка с хэш-кодом выглядит следующим образом:

//-V817 //-VH"3652460326"

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

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

#define TEST_MACRO \
  int a = 0;       \
  size_t b = 0;    \
  b = a; 

void func1()
{
  TEST_MACRO // здесь V1001
}

void func2()
{
  TEST_MACRO // и здесь V1001 
}

В таком случае можно воспользоваться специальной пометкой, которая укажет анализатору, что во всех случаях использования этого макроса срабатывания являются ложноположительными:

//-V:TEST_MACRO:1001

#define TEST_MACRO \
  int a = 0;       \
  size_t b = 0;    \
  b = a; 

void func1()
{
  TEST_MACRO
}

void func2()
{
  TEST_MACRO
}

Также можно просто убрать эти срабатывания. Для этого нужно оставить вот такой комментарий:

//-V::1001:TEST_MACRO
....

Как и в прошлом примере, для макросов возможно указать сразу несколько диагностических правил:

//-V:TEST_MACRO:1001, 105, 201

Вариант с расстановкой комментариев в исходном коде вручную может быть не самым удобным, поэтому плагины PVS-Studio для интегрированных сред разработки позволяют упростить этот процесс до нажатия всего одной кнопки Mark selected messages as False Alarms в контекстном меню:

После нажатия в исходном коде комментарий о ложном срабатывании проставится автоматически:

Если вдруг возникнет необходимость вернуться к срабатываниям, помеченным как ложноположительные, в настройках есть опция DisplayFalseAlarms, позволяющая включать помеченные срабатывания в отчёт анализатора.

Подобная возможность, как и массовое подавление срабатываний, доступна во всех плагинах PVS-Studio для интегрированных сред разработки.

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

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

Отключение диагностических правил на фрагменте кода

Иногда нужно отключить диагностику, причём не глобально, а в конкретном блоке кода. Для этого анализатор PVS-Studio для C и C++ проектов поддерживает специальные директивы #pragma:

  • #pragma pvs(push) — сохраняет текущие настройки включения/отключения диагностик;

  • #pragma pvs(disable: XXXX, YYYY, ...) — выключает диагностики с номерами из списка;

  • #pragma pvs(enable: XXXX, YYYY, ...) — включает диагностики с номерами из списка;

  • #pragma pvs(pop) — восстанавливает предыдущие настройки.

Пример:

void func(int* p1, int* p2)
{
  if (!p1 || !p2)
    return;

#pragma pvs(push)
#pragma pvs(disable: 547)
  if (p1) // V547 не будет выдана
    do_something();
#pragma pvs(pop)

  if (p2) // V547 Expression 'p2' is always true.
    do_other();
}

Чтобы избежать предупреждений о неизвестных #pragma, передайте компилятору флаг:

  • GCC/Clang: -Wno-unknown-pragmas

  • MSVC: -wd4068

Заключение

Мы поговорили о том, как внедрить статический анализатор в уже существующий проект без лишней головной боли с помощью механизма baseline, который позволяет игнорировать старые срабатывания и сосредоточиться на новых. Также мы обсудили, что анализатор не идеален и может выдавать ложноположительные предупреждения, но в PVS-Studio для этого предусмотрены удобные способы подавления срабатываний как массово, так и локально.

Если ранее вы сомневались в том, стоит ли внедрять статический анализатор в свой проект, вы всегда можете попробовать статический анализатор PVS-Studio на своём коде, получив бесплатную лицензию. Переделывая известную поговорку: "Лучше один раз попробовать, чем сто раз услышать или прочитать".

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Valerii Filatov. Seamless static analysis integration and overcoming false positives.

Теги:
Хабы:
+3
Комментарии0

Публикации

Информация

Сайт
pvs-studio.ru
Дата регистрации
Дата основания
2008
Численность
51–100 человек
Местоположение
Россия
Представитель
Андрей Карпов