>
>
Причины внедрить в процесс разработки с…

Андрей Карпов
Статей: 671

Причины внедрить в процесс разработки статический анализатор кода PVS-Studio

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

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

Программные проекты в процессе их развития становятся всё больше. Примеры:

  • Ядро Linux 1.0.0: 176 000 строк кода
  • Ядро Linux 5.0: 26 000 000 строк кода
  • Photoshop 1.0: 128 000 строк кода
  • Photoshop CS 6: 10 000 000 строк кода

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

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

Статический анализ не заменяет, но дополняет другие методологии выявления дефектов, такие как обзоры-кода, юнит-тесты, динамический анализ кода, регрессионные тесты, ручное тестирование и так далее.

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

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

PVS-Studio

Мы рекомендуем внедрить в процесс разработки разработанный нами статический анализатор кода PVS-Studio. Продукт работает в 64-битных системах на Windows, Linux и macOS и может анализировать код, предназначенный для 32-битных, 64-битных и встраиваемых ARM платформ.

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

  • Windows. Visual Studio 2010-2019 C, C++, C++/CLI, C++/CX (WinRT), C#
  • Windows. IAR Embedded Workbench, C/C++ Compiler for ARM C, C++
  • Windows. QNX Momentics, QCC C, C++
  • Windows/Linux. Keil µVision, DS-MDK, ARM Compiler 5/6 C, C++
  • Windows/Linux. Texas Instruments Code Composer Studio, ARM Code Generation Tools C, C++
  • Windows/Linux/macOS. GNU Arm Embedded Toolchain, Arm Embedded GCC compiler, C, C++
  • Windows/Linux/macOS. Clang C, C++
  • Linux/macOS. GCC C, C++
  • Windows. MinGW C, C++
  • Windows/Linux/macOS. Java

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

Для удобства специалистов, которые будут использовать PVS-Studio как SAST инструмент, анализатор отображает свои предупреждения на Common Weakness Enumeration, SEI CERT Coding Standards и стандарт MISRA. Таблицы соответствий диагностик PVS-Studio различным стандартам:

Анализатор может использоваться как самостоятельно, так и интегрироваться с Visual Studio и IntelliJ IDEA. Помимо этого, в последнее время ряд наших клиентов использует PVS-Studio в составе SonarQube. PVS-Studio, будучи подключенным как плагин к SonarQube, является дополнительным источником диагностических сообщений.

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

Анализатор PVS-Studio эффективно выявляет широкий спектр ошибок, начиная от опечаток, до утечек памяти. Это возможно благодаря анализу потока данных, символьному выполнению, сопоставлению с шаблонами, аннотированию методов (в том числе автоматическому). Более подробно о принципах работы вы можете узнать из статьи "Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей".

Почему следует использовать PVS-Studio

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

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

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

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

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

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

Мы обеспечим вам быструю качественную поддержку. На вопросы отвечают непосредственно программисты, разрабатывающие те модули, по которым возник вопрос. Это помогает получить ответы даже в сложных ситуациях. Один из примеров такого общения "Ложные срабатывания в PVS-Studio: как глубока кроличья нора".

Ответы на возражения

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

"Статический анализ будет отнимать часть рабочего времени"

Утверждение "статический анализ будет отнимать часть рабочего времени" в отрыве от контекста является верным. Регулярный просмотр предупреждений статического анализатора, выдаваемых на новый или изменённый код, действительно отнимает время. Однако следует продолжить мысль: но затрачиваемое на это время гораздо меньше, чем траты на выявление ошибок другими методами.

Откуда проистекает мнение о необходимости тратить время на предупреждения статических анализаторов кода?

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

Более подробно эта тема раскрыта в статье "Работа с возражениями: статический анализ будет отнимать часть рабочего времени".

"Статический анализатор очень шумный (выдаёт много ложных срабатываний)"

Как уже было сказано выше, такой вывод делается при использовании ненастроенного анализатора кода. После настройки PVS-Studio можно ожидать, что процент ложных срабатываний составит 10-20%. То есть на пять выданных предупреждений, четыре будут указывать на настоящие ошибки или на код, который с большой вероятностью может стать причиной ошибок в будущем. Пример подобной настройки можно увидеть в статье "Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний".

Ещё одной причиной, искажающей представление о работе анализатора, является желание включить как можно больше предупреждений, без понимания их назначения. Например, если для классического Windows приложения включить набор правил MISRA, ориентированный на встраиваемые системы, анализатор сгенерирует сотни тысяч предупреждений. Никакого практического смысла в них не будет. Особенно лишние диагностики мешают на этапе знакомства с инструментом и формируют неправильное представление о его диагностических возможностях. Избежать этого поможет статья "Как быстро посмотреть интересные предупреждения, которые выдает анализатор PVS-Studio для C и C++ кода?".

"Внедрить статический анализ в процесс разработки очень сложно, долго и дорого"

Очень хорошо эти опасения отражены в этом комментарии:

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

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

Первый подход. "Метод храповика", о котором хорошо рассказывает Иван Пономарёв в своём докладе "Непрерывный статический анализ кода".

Второй подход. Чтобы быстро начать использовать статический анализ, мы предлагаем клиентам PVS-Studio воспользоваться "базой разметки". Общая идея в следующем. Пользователь запустил анализатор и получил множество предупреждений. Раз проект, разрабатываемый много лет, жив, развивается и приносит деньги, то, скорее всего, в отчёте не будет много предупреждений, указывающих на критические дефекты. Другими словами, критические баги так или иначе уже поправлены более дорогими способами или благодаря фидбеку от клиентов. Соответственно, всё, что сейчас находит анализатор, можно считать техническим долгом, который непрактично стараться устранить сразу.

Можно указать PVS-Studio считать эти предупреждения пока неактуальными (отложить технический долг на потом), и больше их не показывать. Анализатор создаёт специальный файл, где сохраняет информацию о пока неинтересных ошибках. И теперь PVS-Studio будет выдавать предупреждения только на новый или измененный код. Причем, всё это реализовано умно. Если, например, в начало некоего .cpp файла будет добавлена пустая строка, то анализатор понимает, что, по сути, ничего не изменилось, и по-прежнему будет молчать. Этот файл разметки можно заложить в систему контроля версий. Файл большой, но это не страшно, так как часто его закладывать смысла нет.

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

Третий подход. Можно заключить с нами контракт и перепоручить нашей команде работу по настройке и интеграции статического анализа. Пример подобной практики: "Как команда PVS-Studio улучшила код Unreal Engine".

"Мы запустили анализатор и не нашли ничего интересного"

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

Более подробно эта тема рассмотрена в статье "Философия статического анализа кода: у нас 100 программистов, анализатор нашел мало ошибок, он бесполезен?".

"Статический анализатор — это дорого, лучше нанять ещё одного программиста/тестировщика"

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

Во-первых, взять дополнительного человека для поиска ошибок - это намного дороже, чем начать использовать анализатор кода. Посчитайте фонд зарплаты человека за год. Добавьте налоги и обустройство рабочего места. Аргумент, что лицензия — это дорого, перестаёт быть аргументом. А ещё статический анализатор, в отличие от человека, не ходит в отпуск, не болеет и не увольняется. Если же мы говорим о больших командах, например, 100 человек, то и для того, чтобы получить какой-то эффект, потребуется нанять несколько человек. Разрыв в пользу статического анализатора становится ещё больше.

Во-вторых, наибольший эффект достигается за счёт синергии использования различных методик поиска ошибок. Какие-то ошибки хорошо обнаруживаются юнит-тестами, какие-то при ручном тестировании и так далее. Представьте ситуацию. В проекте 10 программистов, написано много юнит-тестов, но нет ни одного тестировщика. Качество проекта не устраивает пользователей и появляется идея открыть вакансию тестировщика. Но это не делается под предлогом "лучше нанять ещё одного программиста", пусть будет ещё больше юнит-тестов! Согласитесь, это неправильное решение. Очевидно, что процесс обеспечения качества построен однобоко и намного большую пользу принесёт добавление ручного тестирования. Такая же ситуация и со статическим анализом.

"Динамический анализ более эффективен, чем статический"

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

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

"Юнит-тесты более эффективны, чем статический анализ кода"

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

Статический анализ дополнит юнит-тесты по следующим причинам:

  • Сами тесты никто не тестирует и в них часто содержатся ошибки. В наших статьях мы много раз приводили примеры ошибок в коде юнит-тестов. Соответственно, статический анализ может находить ошибки в тестах, которые, в свою очередь, могут найти ошибки в основном коде приложения.
  • Тестами очень сложно покрыть весь код. Особенно, если речь идёт о коде для обработки нештатных ситуаций. Статические анализаторы проверяют весь код.
  • Некоторые ошибки невозможно или крайне сложно обнаружить юнит-тестами. Пример: V597 (CWE-14).
  • Некоторые ошибки проявляют себя только при обработке больших объёмов данных, и для моделирования таких ситуаций использовать юнит-тесты непрактично. Примером может служить переполнение 32-битной переменной в 64-битной программе (V108, V127).
  • Проще и быстрее найти ошибку запуском статического анализа, чем отлаживая код, когда выяснится, что не отрабатывает юнит-тест. Конечно, юнит-тесты найдут больше ошибок, но если часть из них можно найти более дешевым способом (статическим анализом), почему-бы его не использовать.
  • Мы находим огромное количество ошибок в различных проектах. Многие из этих проектов хорошо покрыты тестами, но, как видите, это не помогает. Так что нет никакой причины, чтобы не начать помимо юнит-тестов использовать ещё и статический анализ кода, тем самым повысив его качество и безопасность.

"Современные бесплатные компиляторы умеют всё то же самое, что и PVS-Studio"

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

Преимущества PVS-Studio:

  • Поддержка пользователей.
  • Богатая инфраструктура (интеграция с другими продуктами).
  • Развитые диагностические возможности.

Первых двух пунктов уже достаточно, чтобы перевесить чашу весов в пользу PVS-Studio. Однако поговорим про диагностики. Мы постоянно развиваем анализатор, чтобы опережать другие инструменты. Например, мы можем находить вот такую интересную ошибку "31 февраля".

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

P.S.

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

Полезные ссылки