Развёрнутый ответ

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

Комментарии


Комментарии написаны к статье «Передаю привет разработчикам компании Yandex». Первый находится здесь. Процитирую его:

Все эти анализаторы кроме пользы добавляют гемор в виде замедления билда, ложных срабатываний, информационного шума и ложного чувства безопасности. Для себя я решил, что профессионалам чем меньше таких тулзов тем лучше — гемор легко перевешивает пользу. А нубасам такое тоже особо не поможет — им бы учиться писать юнит тесты, а не тратить время на затыкание варнингов. Возможно, в Яндексе думают так же.
Хотя если тесты гонять перед релизом, то гемор будет меньше, и можно будет выцедить нормальное соотношение время/ошибки, так что хз.
Дисклеймер: PVS-Studio я не пробовал.


И есть дополнение:

Не забудьте ещё про ваших реальных конкурентов (не де-юре, а де-факто): динамические анализаторы (ASAN, MSAN, TSAN, UBSAN). У них, конечно, есть беда: срабатывают не так быстро и ресурсов требуют больше. Но зато у них есть и преимущество: если уж *SAN чего-то «такое» у вас при фаззинге нашёл, то отбиваться бесполезно — это ошибка, надо чинить. А со статическим анализатором… всякое бывает.
Так что вам нужно влезть в нишу между встроенным в clang/gcc/msvc анализатором (бесплатно и всегда в наличии) и *SAN’ом (сложно и дорого, но зато ложных срабатываний — почти нуль, любую ошибку можно сразу в багтрекер заносить). Так ли велика эта ниша?


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

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

Анализаторы в основном генерируют отвлекающий внимание шум


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

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

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

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

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

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

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

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

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

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

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

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

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

Новичкам проку от статического анализа нет


А нубасам такое тоже особо не поможет — им бы учиться писать юнит тесты, а не тратить время на затыкание варнингов.

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

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

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

Примечание. Юнит-тесты, кстати, тоже не панацея, и статический анализатор дополняет эту методологию, а не конкурирует с ней. См. статью «Как статический анализ дополняет TDD».

Можно прогонять статический анализатор перед релизом


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

Это совершенно неправильный способ использования анализатора! Хуже только вариант, когда статический анализ вообще не используется или используется раз в 5 лет.

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

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

Здесь вновь уместна аналогия с предупреждениями компилятора. Допустим, полностью отключаются предупреждения, и 3 месяца разрабатывается проект. А затем, за день до релиза, все эти предупреждения компилятора включаются. Согласитесь, это глупость какая-то.

Ещё здесь будет уместно предложить познакомиться со статьёй коллеги, посвященной бестолковости разовых запусков анализатора: «Философия статического анализа кода: у нас 100 программистов, анализатор нашел мало ошибок, он бесполезен?».

Динамический анализ — конкурент статическому анализу


Не забудьте ещё про ваших реальных конкурентов (не де-юре, а де-факто): динамические анализаторы (ASAN, MSAN, TSAN, UBSAN). У них, конечно, есть беда: срабатывают не так быстро и ресурсов требуют больше. Но зато у них есть и преимущество: если уж *SAN чего-то «такое» у вас при фаззинге нашёл, то отбиваться бесполезно — это ошибка, надо чинить. А со статическим анализатором… всякое бывает.

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

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

Мы не рассматриваем динамические анализаторы как конкурентов, так как профессиональные программисты не ставят вопрос «Что выбрать?». Они используют обе эти технологии, ведь и та, и та помогает ответить на вопрос: «Что я ещё могу сделать для повышения качества кода?».

Примечание

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

  • Статический и динамический анализ кода.
  • Проверяем код динамического анализатора Valgrind с помощью статического анализатора.

Сложно влезть в нишу между компиляторами и динамическими анализаторами


Так что вам нужно влезть в нишу между встроенным в clang/gcc/msvc анализатором (бесплатно и всегда в наличии) и *SAN’ом (сложно и дорого, но зато ложных срабатываний — почти нуль, любую ошибку можно сразу в багтрекер заносить). Так ли велика эта ниша?

Ниша широка, и в ней замечательно помещается не только анализатор PVS-Studio, но и инструменты множества других компаний, таких как SonarSource, Synopsys (бывший Coverity), Gimpel Software, Rogue Wave Software и так далее.

Почему ниша широка? Ответ прост: озвученное в комментарии никак не ограничивает статические анализаторы кода. У одной границы поставлены динамические анализаторы. Но, как выяснили ранее, там нет конкуренции, а дружественный симбиоз.

У другой границы — компиляторы. Да, компиляторы становятся всё умнее. Однако инструменты статического анализа тоже не стоят на месте и быстро развиваются.

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

  • Проверка LLVM (Clang) (август 2011), вторая проверка (август 2012), третья проверка (октябрь 2016)
  • Проверка GCC (август 2016)
  • Код Visual С++ закрыт. Зато можно проверить библиотеки и продемонстрировать возможности PVS-Studio. Проверка библиотек Visual C++ (сентябрь 2012), вторая проверка (октябрь 2014), третья проверка (май 2017)

PVS-Studio я не пробовал


Зря, попробуйте:). Многим нравится, и они становятся нашими клиентами.

Причём попробовать PVS-Studio очень просто. Зайдите на страницу продукта и скачайте демонстрационную версию.

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

Всем спасибо за внимание и желаю безбажного кода.

© Habrahabr.ru