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

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

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

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

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

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

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


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

>
>
В чём проблемы первого отчёта статическ…

В чём проблемы первого отчёта статического анализатора и как их исправить?

09 Дек 2021

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

0896_FirstReportSA_ru/image1.png

Что такое статический анализ

Статический анализ – это технология, которая позволяет находить ошибки и потенциальные уязвимости в исходном коде без его фактического выполнения. Чтобы было проще понять, как это выглядит, давайте сразу на примере. Не так давно состоялся релиз LLVM 13.0.0, и мы его проверили. Там были найдены интересные ошибки, и вот одна из них:

bool operator==(const BDVState &Other) const {
  return OriginalValue == OriginalValue && BaseValue == Other.BaseValue &&
    Status == Other.Status;
}

Анализатор выдаёт на этот фрагмент следующее предупреждение:

[CWE-571] There are identical sub-expressions to the left and to the right of the '==' operator: OriginalValue == OriginalValue RewriteStatepointsForGC.cpp 758

Как мы видим, в первом сравнении опечатались и вместо Other.OriginalValue написали просто OriginalValue. Это классическая ошибка в методах сравнения, и привести она может к совершенно разным и не очень приятным результатам.

Проблемы первого отчёта

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

0896_FirstReportSA_ru/image2.png

Так выглядит окно плагина PVS-Studio для Visual Studio 2022. Здесь мы можем видеть разные кнопки сверху, которые нужны для фильтрации, а также список предупреждений. Смысл ошибок в данный момент не важен. Я хочу обратить внимание на количество выданных предупреждений:

0896_FirstReportSA_ru/image4.png

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

Ну ладно, допустим, вы решаетесь посмотреть, что же там такое выдал анализатор. И тут вас встречает вторая проблема — одинаковые предупреждения:

0896_FirstReportSA_ru/image6.png

С точки зрения анализатора, тут всё нормально. Ну да, в коде найдено много одинаковых ошибок, и он об этом говорит. Однако мы говорим сейчас про первое знакомство с инструментом. В этот момент хочется разнообразия, и смотреть на 4 одинаковых предупреждения подряд – это некруто.

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

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

Как бороться с проблемами первого отчёта

Для решения описанных ранее проблем я хочу предложить старую добрую работу с весами. Смотрите, у статического анализатора есть диагностические правила, каждое из которых отвечает за определённый паттерн ошибки. Поэтому вы садитесь, анализируете все созданные диагностики и задаёте им начальный вес. Наилучшие диагностики получают больший вес, наихудшие – меньший. Что такое наилучшая диагностика? Это диагностика, которая имеет наименьший шанс ложного срабатывания, находит опасную ошибку или является очень интересной. Здесь на ваше усмотрение.

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

  • категория предупреждения;
  • предупреждения на тестах;
  • количество выданных предупреждений на одну строку одного и того же файла;
  • частота появления одной и той же диагностики.

И тут, чтобы было проще понять, что я имею в виду, я буду говорить на примере. Примером является реализация этого механизма в PVS-Studio под названием Best Warnings. Начнём по порядку.

Категория предупреждения

Это изменение веса с учётом какой-то изначальной группировки предупреждений. Например, у нас все диагностики делятся на 3 группы: High, Medium, Low. High – наиболее достоверные ошибки, и их вес мы не трогаем. Medium – ошибки средней достоверности, и мы понижаем их вес на определенный коэффициент.

Предупреждения на тестах

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

Количество выданных предупреждений на одну строку

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

Частота появления одной и той же диагностики

Если количество предупреждений одной диагностики составляет более N% от числа всех предупреждений, то, скорее всего, это неинтересные предупреждения. Обычно такое связано со стилем написания кода или использованием неудачных макросов в C или C++ коде.

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

Остаётся решить только первую проблему – большое количество предупреждений. Для этого вы просто сортируете все предупреждения по весам и выдаете N самых тяжелых. Тем самым вы как бы изучаете отчёт вместо человека и выдаёте ему самую мякотку.

Как это все выглядит в PVS-Studio

Мы добавили в наши плагины для Visual Studio кнопку, при нажатии на которую выполняется описанный ранее механизм. Давайте вернёмся к примеру отчёта выше и прогоним его через этот механизм:

0896_FirstReportSA_ru/image8.png

Вот отчёт. И теперь вместо того, чтобы сразу его анализировать, мы нажимаем 2 кнопки. Первая:

0896_FirstReportSA_ru/image9.png

И вторая:

0896_FirstReportSA_ru/image11.png

После этого отчёт начинает выглядеть вот так:

0896_FirstReportSA_ru/image13.png

Как вы видите, осталось всего 10 предупреждений. Их посмотреть намного проще, чем 2000 :)

Также мы добавили разнообразие в выданных предупреждениях. Коды разнообразные, и мы решили допускать не более 2 одинаковых предупреждений.

Заключение

Давайте подытожим. Добавив механизм работы с весами, решается сразу ряд проблем. Смотреть первый отчёт становится проще, так как количество выданных предупреждений становится реальным для анализа. Сами предупреждения становятся достовернее и разнообразнее. Также уменьшаются затраты по времени на знакомство с инструментом. Например, анализ Wolfenstein с учётом установки анализатора и просмотра предупреждений занял у меня около 10-15 минут.

Если после прочтения вам стало любопытно посмотреть, как это работает вживую, то вам сюда.

Спасибо за внимание.

Популярные статьи по теме
Как увеличилась производительность LINQ в .NET 7?

Дата: 30 Ноя 2022

Автор: Михаил Евтихевич

В новой версии .NET улучшилась производительность методов Min, Max, Average и Sum для массивов и списков. Как вы думаете, во сколько раз увеличилась скорость их выполнения? В 2 раза, в 5? Нет, они ст…
Что такое катастрофический возврат и как регулярное выражение может стать причиной ReDoS-уязвимости?

Дата: 03 Ноя 2022

Автор: Андрей Москалёв

Регулярные выражения – очень полезный и удобный инструмент для поиска и замены текста. Однако в некоторых случаях они могут привести к зависанию системы или даже стать причиной уязвимости к ReDoS-ата…
Обзор нововведений в C# 11

Дата: 21 Окт 2022

Автор: Константин Волоховский

C# 11 выходит уже совсем скоро, так что пора детально изучить новые особенности, которые появятся в языке. И хотя их немного, среди них есть довольно интересные: обобщённая математика, исходные строк…
Есть ли жизнь без RTTI: пишем свой dynamic_cast

Дата: 13 Окт 2022

Автор: Владислав Столяров

В современном С++ осталось не так много вещей, которые не подходят под парадигму "Не плати за то, что не используешь". Одна из них – dynamic_cast. В рамках данной статьи мы разберёмся, что с ним не т…
Особенности реализации List в C#

Дата: 04 Окт 2022

Автор: Артём Ровенский

List является одной из самых популярных коллекций в C#. Давайте разберёмся в некоторых особенностях работы с ним и посмотрим на внутреннюю реализацию его отдельных частей.

Комментарии (0)

Следующие комментарии
Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо