Команда PVS-Studio пишет много статей на разные интересные темы. Но вот вопросы взаимодействия с самим анализатором затрагиваются редко. Исправим этот недочёт обзорной статьёй, описывающей плагин PVS-Studio для среды Visual Studio 2022.

Что такое статический анализ кода и зачем он нужен

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

С одной стороны, хочется регулярно осуществлять обзор кода. С другой – это слишком дорого. Компромиссным решением являются инструменты статического анализа кода. Они без устали обрабатывают исходные тексты программ и выдают программисту рекомендации обратить повышенное внимание на определенные участки кода. Конечно, программа не заменит полноценного обзора кода, выполняемого коллективом программистов. Однако соотношение польза/цена делает использование статического анализа весьма эффективной практикой, применяемой многими компаниями. Если читателя интересуют конкретные числа, то предлагаю познакомиться со статьёй "PVS-Studio ROI".

Существует большое количество коммерческих и бесплатных статических анализаторов кода. Их список имеется на сайте Wikipedia: List of tools for static code analysis. Список языков, для которых существуют статические анализаторы кода, также достаточно велик (Си, Си++, C#, Java, Ada, Fortran, Perl, Ruby, ...). Естественно, мы будем рассказывать вам об анализаторе PVS-Studio.

Главное преимущество статического анализа состоит в возможности существенного снижения стоимости устранения дефектов в программе. Чем раньше ошибка выявлена, тем меньше стоимость её исправления. Так, согласно данным, приведённым в книге Макконнелла "Совершенный Код", исправление ошибки на этапе тестирования обойдётся в десять раз дороже, чем на этапе конструирования (написания кода):

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

Статический анализатор кода PVS-Studio

PVS-Studio – статический анализатор, выявляющий ошибки и потенциальные уязвимости в исходном коде приложений на языках C, C++ (также поддерживаются расширения: C++/CLI и C++/CX), C# и Java на платформах Windows, Linux и macOS. Анализатор интегрируется в среды Visual Studio 2010 – 2022, IntelliJ IDEA и Android Studio, JetBrains Rider и CLion. В этой статье мы подробно рассмотрим работу PVS-Studio для проверки кода на языках C, C++ и C# в Visual Studio. Вы также можете почитать про использование PVS-Studio в других IDE по соответствующим ссылкам:

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

Начальные настройки

Анализатор готов к работе сразу после установки. В большинстве случаев вам не потребуется ничего настраивать, чтобы осуществить первый запуск. Единственная настройка, которая может понадобиться вам в начале, это исключение сторонних библиотек. Вы ведь всё равно не будете ничего править в исходных файлах, например, библиотеки jpeg, поэтому незачем её проверять. Вдобавок исключение лишних папок сократит время анализа проекта. Исключаемые из анализа директории задаются здесь: Extensions > PVS-Studio > Options... > Don't Check Files > PathMasks.

Если в полном пути файла есть одно из указанных имён, то анализ выполняться не будет. По умолчанию, в список уже включены имена некоторых директорий. Однако в вашем проекте папка с библиотекой zlib может называться не "zlib", а, например, "zip_lib". Поэтому следует отредактировать этот список. Для начала редактирования следует нажать кнопку с тремя точками.

Примеры допустимых масок для списка PathMasks:

  • c:\Libs\ — будут исключены все файлы проекта, расположенные в данной папке и её подпапках;

  • \Libs\ или *\Libs\* — будут исключены все файлы, расположенные в директориях, путь до которых содержит подпапку "Libs". Если символы "*" не указаны, они все равно будут автоматически добавлены, поэтому оба варианта записи одинаковы.

  • Libs или *Libs* — исключены будут все файлы, путь до которых содержит подпапку, имеющую 'Libs' в качестве имени либо фрагмента имени. Также в этом случае будут исключены файлы, содержащие Libs в имени, например, c:\project\mylibs.cpp. Во избежание путаницы рекомендуем всегда использовать слеши.

Помимо исключений целых папок можно задавать маски для исключения отдельных файлов. Для этого существует настройка FileNameMasks. Подробнее, как работать со списками исключений, можно познакомиться в документации: Settings: Don't Check Files.

Проверка проекта

По завершении первичных настроек вы можете приступить к проверке проекта. PVS-Studio для Visual Studio поддерживает проверку C++ (.vcxproj) и C# (.csproj) проектов. Также можно проверить решение, содержащее проекты таких типов, целиком. Для этого выберите пункт меню Extensions > PVS-Studio > Check > Solution.

Также возможно запустить анализ только на определённых проектах и/или файлах, выбранных в Solution Explorer. Для этого после выбора элементов в Solution Explorer необходимо нажать правой кнопкой мыши и выбрать пункт Analyze with PVS-Studio:

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

Работа со списком предупреждений анализатора

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

  1. Собственно, окно PVS-Studio.

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

  3. Кнопка включает сообщения "что-то пошло не так". Например, не удаётся препроцессировать один из файлов.

  4. Переход к предыдущему/следующему предупреждению. При этом открывается соответствующий файл, и курсор ставится на строку с потенциальной ошибкой. Также, чтобы выбрать диагностику из списка, совершите двойной клик мышью. Можно назначить горячие клавиши для осуществления переходов к предыдущему/следующему предупреждению. По умолчанию это Alt+'[' и Alt+']'.

  5. Кнопки, включающие предупреждения разных уровней. Сейчас включены все уровни диагностик. При этом в окне показывается 312 предупреждений первого уровня, 1354 предупреждений второго уровня и 1405 третьего. Уровень предупреждения показывается в левой части окна в виде полоски, соответствующей по цвету полоске на кнопке уровня.

  6. Активные наборы диагностических правил. General — диагностики общего назначения, Optimization — микрооптимизации, 64-bit — 64-битные диагностики, OWASP – предупреждения, соответствующие стандарту OWASP ASVS или относящиеся к OWASP Top-10. Сейчас в окне отображаются не все виды предупреждений.

  7. Показывает количество предупреждений, помеченных как ложные (false positives). Включить/выключить отображение размеченных предупреждений можно в настройках, Extensions > PVS-Studio > Options... > Specific Analyzer Settings > Display False Alarms.

  8. Быстрые фильтры. Можно, например, оставить в списке только предупреждения с кодом V501, находящиеся в проекте XYZ.

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

Таблица с предупреждениями анализатора разбита на следующие колонки:

  • Уровень. Уровень достоверности, что найдена именно ошибка. 1-й уровень (красный) — наиболее подозрительные места. 3-й (жёлтый) — скорее всего, несущественная неточность в коде;

  • Звездочка. У неё нет конкретного назначения. Пользователь может интерпретировать её по своему усмотрению. Например, он может отметить наиболее интересные предупреждения для дальнейшего внимательного анализа. Аналогия — отметка звёздочками писем в почтовой программе типа Thunderbird или Outlook.

  • ID. Уникальный номер предупреждения. Может пригодиться при работе с большим списком. Например, можно перейти к предупреждению с определенным номером (см. пункт "Navigate to ID..." в контекстном меню). Можно отключить эту колонку, используя контекстное меню.

  • Code. Код предупреждения. Если щелкнуть по нему мышкой, то откроется страница с описанием предупреждения.

  • CWE. Позволяет идентифицировать предупреждение по CWE ID (Common Weakness Enumeration). При нажатии на ссылку можно посмотреть описание данного CWE в сети. Можно отключить эту колонку, используя контекстное меню.

  • SAST. Тот же функционал, что описан выше, только для стандартов MISRA, AUTOSAR, SEI CERT или OWASP. Можно отключить эту колонку, используя контекстное меню.

  • Message. Текст предупреждения анализатора.

  • Project. Имя проекта. Можно отключить эту колонку, используя контекстное меню.

  • File. Имя файла. Важно! Обратите внимание, что после некоторых имён файлов стоит многоточие. Пример: "FileName.cpp(...)". Кликнув на ячейку таблицы с именем файла, вы получите список всех строк кода (эти строки могут находиться в разных файлах), которые относятся к этому предупреждению. При этом есть возможность перейти к каждой из строк в списке.

  • Line. Номер строки, на которую было выдано предупреждение.

  • FA. Индикатор того, что предупреждение анализатора отмечено как ложно-положительное.

Да, прочитать всё это было утомительно. Однако, уверяю вас, начав пользоваться, вы быстро освоитесь с инструментом. И нажимать что-то для настройки будете крайне редко.

Отображение лучших предупреждений анализатора

При первом использовании анализатора результат может напугать и/или запутать разработчика, потому что в отчёте анализатора может оказаться огромное количество предупреждений о потенциальных ошибках и уязвимостях. Учитывая данный сценарий, в плагин для Visual Studio был добавлен механизм Best Warnings. Кнопка для включения/отключения данного механизма расположилась в меню Additional Actions:

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

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

Контекстное меню

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

Меню достаточно простое, и не стоит перегружать статью описанием каждого из пунктов. Если что-то непонятно, можно подсмотреть в документации.

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

Однако стоит упомянуть одну очень полезную фичу. Помните, что в настройках можно добавить папки/файлы для исключения. Так вот, добавлять что-то намного проще, чем кажется!

Обратите внимание на пункт "Don't check files and hide all messages from...". При нажатии на него выпадает список путей, которые можно добавить в исключение.

Можно выбрать как отдельный файл, так и одну из директорий. На рисунке показано, что выбирается папка "Sources\Sandbox.Game\Game\Entities". Это значит, что все файлы в этой папке и всех подпапках будут исключены из анализа. Более того, все сообщения, относящиеся к этим файлам, сразу исчезнут из списка. Не нужно перезапускать анализ, чтобы убрать все сообщения, относящиеся к тестам.

Режим инкрементального анализа

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

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

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

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

На самом деле, чем описывать этот режим, проще попробовать поработать с ним. Вы пишете код, как и раньше. А, если надо, анализатор потревожит вас. Попробуйте!

Мы сами постоянно используем этот режим. Да, мы тоже иногда допускаем ошибки при кодировании. И возможность их сразу исправить существенно сокращает время на обнаружение дефекта и попытку понять, отчего программа ведёт себя не так, как планировалось. Очень обидно потратить минут 15-20 на отладку, чтобы потом обнаружить опечатку в индексе. Вот один из случаев, когда анализатор PVS-Studio нашёл ошибку сам в себе, сразу после того, как она появилась в коде:

if (in[0] == '\\' && in[1] == '.' && in[1] == '\\')
{
  in += 2;
  continue;
}

Но это, конечно, цветочки. Анализатор PVS-Studio может оказаться намного полезнее. Вот один из отзывов о нашем анализаторе: "Пример использования статического анализатора". Текст заставляет задуматься.

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

Межмодульный анализ проектов

Анализатор PVS-Studio для C# построен на основе Roslyn API, которое позволяет производить межмодульный анализ C# проектов. С межмодульным анализом C++ проектов всё намного сложнее, поэтому этот механизм только недавно появился в PVS-Studio. Межмодульный анализ позволяет собрать информацию не о каждом исходном файле отдельно, а обо всём проекте в целом. Это позволяет увеличить точность и качество анализа. Более подробную информацию об особенностях межмодульного анализа C++ проектов в PVS-Studio вы можете найти в статье "Межмодульный анализ C++ проектов в PVS-Studio".

Диагностики PVS-Studio

Будем кратки. Невозможно лаконично описать все диагностики, которые имеются в PVS-Studio. Полный список диагностик и их подробное описание можно найти в документации: Описание диагностируемых ошибок. Ограничимся таблицей, в которой диагностики сгруппированы по типам. Некоторые диагностики входят более чем в одну группу. Дело в том, что деление весьма условно. Например, опечатка может приводить к использованию неинициализированной памяти. Некоторым ошибкам наоборот места в таблице не нашлось, слишком они специфические. Тем не менее, таблица в целом даёт представление о функциональности PVS-Studio.

Как видите, анализатор максимально проявляет себя в таких областях, как поиск ошибок, возникших из-за опечаток, Copy-Paste. Хорошо диагностирует проблемы, которые связаны с безопасностью кода.

Как всё это работает на практике, можно узнать, заглянув в базу ошибок. Мы собираем в эту базу все ошибки, которые нашли, проверяя различные Open Source проекты.

SAST

PVS-Studio является средством статического тестирования защищённости приложений (Static Application Security Testing, SAST). Анализатор может выявлять потенциальные уязвимости в коде проекта и показывать соответствующий идентификатор ошибки в определённой классификации.

PVS-Studio поддерживает следующие классификации ошибок:

Включить отображение кодов CWE/SAST можно по контекстному меню в окне анализатора по пути Show Columns > CWE / SAST

Либо в меню сверху (Extensions > PVS-Studio > Display CWE Codes in Output Window / Display SAST Codes in Output Window)

Диагностики MISRA/AUTOSAR/OWASP включаются отдельно в настройках:

Подробнее про эти классификации можно прочитать здесь.

Проверка проектов из командной строки

Также имеется возможность использования анализатора PVS-Studio из командной строки. Для этого имеется утилита PVS-Studio-Cmd.exe. Подробную информацию по утилите и её параметрам можно найти в документации.

Вот так выглядит запуск данной утилиты:

После выполнения мы получим plog-файл с отчётом, путь до которого мы указали в параметрах запуска. Этот отчёт можно преобразовать в другие форматы с помощью утилиты PlogConverter.exe, а для просмотра отчёта в IDE достаточно двойного клика по plog-файлу в проводнике.

Также файл отчёта можно открыть в меню расширения по пути Extensions > PVS-Studio > Open/Save > Open Analysis Report...

Подавление ложных предупреждений

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

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

Заключение

Конечно, здесь мы рассказали не всё об инструменте. Если рассказывать всё, то статья превратится в документацию. Цель была показать, как легко можно работать с инструментом в рамках среды Visual Studio. Про другие среды и режимы работы можно почитать в документации и других статьях, расположенных на нашем сайте. Там, кстати, много интересного для программистов. Заходите побродить.

Стоит отметить, что PVS-Studio работает не только в среде от Microsoft. Мы также поддерживаем язык Java, можем работать под Linux и macOS, интегрироваться в CMake и много чего еще. Подробнее можно узнать в документации.

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

Дополнительные ресурсы

  1. Обзор кода (code review).

  2. Статический анализ кода.

  3. SAST.

  4. Технологии статического анализа кода PVS-Studio.

  5. Скачать PVS-Studio и попробовать в деле.

  6. Обсудить цену на анализатор PVS-Studio для вашей команды и способах его приобретения: купить PVS-Studio.

  7. Что нового появилось в PVS-Studio в 2021 году.

  8. Ответы на вопросы, которые часто задают на конференциях.

  9. Как внедрить статический анализатор кода в legacy проект и не демотивировать команду.

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Valery Komarov. PVS-Studio for Visual Studio 2022.