Статический анализ важно проводить регулярно, но что делать, если анализ всего проекта занимает много времени? В статье отвечаем на этот вопрос и делимся рецептами для конкретных ситуаций.
Статический анализ помогает находить в исходном коде ошибки и уязвимости, однако наибольшую пользу можно получить только от его регулярного использования. Здесь мы можем столкнуться с другой проблемой: при большой кодовой базе проекта его полный анализ может занимать довольно много времени.
Есть несколько решений этой ситуации, например, режим инкрементального анализа, позволяющий анализировать только тот код, который появился или изменился с момента предыдущего запуска анализатора.
Представим некоторого абстрактного разработчика, который работает над большим проектом. Допустим, он внёс небольшую правку в код и теперь хочет посмотреть, что с ней новых ошибок в коде не появилось. В таком случае зачем разработчику проводить полный анализ проекта, если он работает над вполне конкретной фичей во вполне определённой части этого проекта? Достаточно будет провести анализ только тех фрагментов кода, которые изменялись.
Как раз для подобных сценариев PVS-Studio имеет специальную настройку в IDE плагинах. Например, в IDE Visual Studio во вкладке Extensions > PVS-Studio есть пункт Analysis after Build (Modified files only).
При включении этого режима анализ изменённых файлов будет проводиться после каждой успешной сборки проекта в Visual Studio. Индикатором того, что идёт анализ, является иконка PVS-Studio в трее.
Подобный режим есть и в плагине PVS-Studio для IntelliJ IDEA. Для включения автоматического проведения инкрементального анализа после каждой сборки нужно поставить соответствующую галочку в настройках плагина:
Также это есть в плагине PVS-Studio для Qt Creator.
Таким образом, каждый разработчик, использующий PVS-Studio на своей машине, сможет оперативно реагировать на срабатывания анализатора и не допускать попадания ошибок на следующие этапы разработки проекта.
Использование статического анализа на этапе непрерывной интеграции CI/CD пайплайна позволит автоматизировать процесс проведения статического анализа и сделать его регулярным. В CI/CD статический анализ также не требуется проводить на всём коде. Мы точно знаем, что весь предыдущий код работает, нам нужно только проверить то, что добавилось с последним коммитом.
Более того, нужно понимать, что помимо проведения статического анализа в пайплайне также будут присутствовать тесты и, даже при самом идеальном распределении модульных, интеграционных и функциональных тестов, они тоже занимают время. Поэтому использование инкрементального анализа может помочь не только в оперативном получении результата, но и в ускорении работы пайплайна.
Способ включения инкрементального режима в PVS-Studio зависит от утилиты, используемой для запуска анализатора.
При анализе CMake проектов для включения режима инкрементального анализа нужно добавить в команду специальный флаг:
pvs-studio-analyzer analyze ... \
--incremental ...
Для других компиляторов следует воспользоваться отслеживанием запуска компиляторов.
На Linux для этого используется режим trace
в том же pvs-studio-analyzer
. В этом режиме анализатор будет отслеживать и логировать дочерние процессы сборочной системы, а также найдёт среди них процесс компиляции. Чтобы проверить только последние изменения, следует воспользоваться инкрементальной сборкой, а после просто запустить анализ:
pvs-studio-analyzer trace \
-- %команда_для_сборки_проекта%
pvs-studio-analyzer analyze ...
На Windows для отслеживания запуска компиляторов используется утилита CLMonitor.exe. В этом случае, как и при использовании pvs-studio-analyzer
в режиме trace
, можно использовать режим инкрементальной сборки, чтобы и при мониторинге компиляции проверялся только новый код.
Для проектов на MSBuild для проведения анализа используются утилиты командных строк PVS-Studio_Cmd.exe
(Windows) и pvs-studio-dotnet
(Linux, macOS). В этих утилитах также присутствует флаг –incremental
, но он имеет следующие дополнительные настройки:
Scan
— проанализировать все зависимости, чтобы определить, на каких файлах необходимо провести анализ. Запуск в таком режиме должен производиться перед сборкой проекта, а результаты сканирования анализатор запишет во временные директории .pvs-studio
. Сам анализ при таком режиме выполнен не будет;AppendScan
— выполняет то же, что и в пункте выше, но учитывает изменения, проведённые с момента последней сборки, а также все предыдущие изменения (Scan
учитывает только изменения с момента предыдущей сборки);Analyze
— выполнить анализ (предварительно нужно запустить в режиме Scan
). Анализ проводится для тех файлов, которые изменились с момента предыдущего анализа;ScanAndAnalyze
— объединяет пункты выше, т. е. сначала анализирует, какие файлы в проекте изменились, а после проводит их анализ.Для Java проектов есть возможность включения инкрементального анализа с помощью специального флажка в скриптах сборки.
При использовании Maven плагина:
<plugin>
<groupId>com.pvsstudio</groupId>
<artifactId>pvsstudio-maven-plugin</artifactId>
....
<configuration>
<analyzer>
....
<incremental>true</incremental>
....
</analyzer>
</configuration>
</plugin>
При использовании Gradle плагина:
apply plugin: com.pvsstudio.PvsStudioGradlePlugin
pvsstudio {
....
incremental = true
....
}
В PVS-Studio версии 7.34 в утилитах командных строк PVS-Studio_Cmd
(Windows) и pvs-studio-dotnet
(Linux, macOS) появился режим проверки модифицированных файлов, который является аналогом инкрементального анализа.
Анализатор получает и сохраняет в кэш зависимостей компиляции информацию о модификации файлов. Кэш зависимостей — это список файлов исходного кода проекта и их зависимостей.
В режиме проверки модифицированных файлов вычисляется хэш для каждого исходного файла, представленного в кэше. При последующем запуске хэш в кэше зависимостей сравнивается с фактическим значением хэша файла. Если хэши различаются, файл будет проанализирован.
Этот режим включается с помощью специального флага ‑‑analyzeModifiedFiles
(-F
). Пример команды с использованием такого режима анализа:
PVS-Studio_Cmd.exe -t MyProject.sln -F ^
-D path\to\depCacheDir ^
-R depCacheRoot ^
-o analysis_report.json
Если файл кэша зависимостей компиляции отсутствует, то он будет сгенерирован, и при этом запустится анализ всех исходных файлов проекта. Для того, чтобы этого не произошло, можно запустить анализатор в режиме генерации файлов кэшей зависимостей без непосредственного запуска анализа (флаг -W
) с вычислением хэшей для файлов исходного кода (флаг -H
). Для этого воспользуйтесь следующей командой:
PVS-Studio_Cmd.exe -t MyProject.sln -W -H ^
-D path\to\depCacheDir ^
-R depCacheRoot
В таком случае будут сгенерированы файлы кэшей зависимостей, но не будет запущен анализ. Следующий запуск анализа модифицированных файлов будет анализировать уже только добавленные или изменившиеся файлы исходного кода проектов.
Проведём эксперимент. Для него я буду использовать проект ScreenToGif, который мы относительно недавно проверяли на наличие багов. Предлагаю на конкретном примере посмотреть, сколько времени может сэкономить нам этот режим.
Примечание. Для замеров времени мной был написан небольшой скрипт, который запускает анализатор в нужных режимах, сохраняя время начала и конца его работы.
На анализ всего проекта анализатору потребовалось 87 секунд, для генерации файлов кэшей зависимостей — 14 секунд, а для анализа изменённых файлов — 17 секунд.
Таким образом, мы сократили время регулярного анализа с 87 до 31 секунды. Разница почти в три раза! При этом проект, который был использован для замеров, довольно небольшой, поэтому в других проектах разница может быть поистине драматичной.
Показанный режим будет полезен при анализе коммитов и запросов на слияние (pull/merge requests). Опять же, мы знаем, что в главной ветке нашего репозитория с кодом всё в порядке, но нужно понять, что в новом коде не таится страшного жучка, которого потом придётся вылавливать.
Для проверки коммита или запроса на слияние воспользуйтесь следующим алгоритмом:
Другим вариантом проверки Pull Request'ов или коммитов с помощью PVS-Studio является анализ списка файлов. Он доступен в утилитах командных строк PVS-Studio_Cmd.exe
и pvs-studio-analyzer
/CompilerCommandsAnalyzer.exe
.
Для использования анализа списка файлов нужно указать специальный флаг:
‑‑sourceFiles
или -f
для PVS-Studio_Cmd.exe
;‑‑source-files
или -S
для pvs-studio-analyzer
.В этом флаге нужно указать путь до файла, содержащего список путей до файлов исходного кода, которые нужно проанализировать.
При первом запуске анализа с использованием этого флага анализатор строит список зависимостей, добавляя помимо указанных файлов те, от которых они зависят. Информация о зависимостях сохраняется в отдельный файл кэша зависимостей для каждого проекта. При каждых последующих запусках анализа списка файлов информация в кэше зависимостей будет добавляться или обновляться для:
После обновления информации анализ будет запущен для всех файлов из списка, переданного во флаге, а также для всех файлов, которые от них зависят.
Для поддержания кэша зависимостей в актуальном состоянии требуется запускать анализ с этим флагом для каждого изменения исходных файлов, либо одновременно для всех изменившихся файлов из нескольких коммитов. Пропуск анализа изменений исходных файлов или отдельные запуски анализа изменённых файлов в порядке, отличном от порядка модификации, может привести к последующему пропуску анализа из-за изменений в структуре зависимостей проекта.
Однако для случаев, когда гарантировать передачу всех изменяющихся файлов в проекте нельзя, есть флаги для перегенерации кэшей зависимостей с запуском анализа:
‑‑regenerateDependencyCache
или -G
для PVS-Studio_Cmd.exe
;‑‑regenerate-depend-info
для pvs-studio-analyzer
.А также для перегенерации кэшей без запуска анализа:
‑‑regenerateDependencyCacheWithoutAnalysis
или -W
для PVS-Studio_Cmd.exe
;‑‑regenerate-depend-info-without-analysis
для pvs-studio-analyzer
.С помощью этих флагов можно восстановить актуальность кэшей, сгенерировав их снова.
Короткий ответ: всё равно нужен. Теперь перейдём к длинному.
Описанные выше ситуации требуют максимально оперативного реагирования со стороны анализатора. Именно поэтому мы в абстрактных примерах выше пришли к выводу о необходимости применения инкрементального анализа или других похожих режимов. Однако проверка всего проекта тоже необходима. После того, как мы проанализировали работу конкретных изменённых частей проекта, нам необходимо удостовериться, что он весь не стал работать хуже.
Например, вполне вероятно, что тот метод, который недавно был изменён разработчиком, использовался в другой части проекта, и теперь та, другая часть проекта, ведёт себя не так, как было рассчитано изначально.
Оптимальным решением будет запускать анализ всего проекта во время ночных сборок. В случае появления срабатываний анализатора можно, например, отправить результаты анализа всем причастным к тому коду, который вызвал срабатывания (у PVS-Studio для этого есть специальный инструмент — Blame Notifier).
В этой статье мы рассмотрели конкретные ситуации, в которых важно сэкономить время при регулярном использовании статического анализа. Из способов решения мы разобрали инкрементальный анализ, анализ модифицированных файлов и анализ списка файлов. Все ситуации были рассмотрены с конкретными примерами использования статического анализатора PVS-Studio. За подробной информацией по его использованию можно обратиться к нашей документации по ссылке.
0