Ответ

К одной из моих статей прозвучали комментарии, в которых собрано так много предубеждений касательно статического анализа кода, что я решил оформить ответ в виде отдельной публикации. Надеюсь, ответ позволит автору комментариев и всем сомневающимся программистам по-новому взглянуть на инструменты статического анализа вообще, и 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 чего-то «такое» у вас при фаззинге нашёл, то отбиваться бесполезно — это ошибка, надо чинить. А со статическим анализатором… всякое бывает.

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

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

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

Примечание

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


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


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

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

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

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

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


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


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

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

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

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

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


  1. andrew_tch
    05.12.2017 11:43
    +5

    По первому комментарию — как только программист говорит что он профессионал и ему тулзов не надо, его можно списывать.


    1. atd
      05.12.2017 12:18
      +1

      Я бы не был так категоричен (списывать), но это вполне популярная стадия развития программиста. Через некоторое время большинство таких «профессионалов» понимают свои ограничения.

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


      1. Jef239
        05.12.2017 12:53
        +1

        А что делать, если у человека реально один баг на 10 тысяч строк? Лезть в нему в сорцы и впихивать баги искусственно? :-)


        1. dimkss
          05.12.2017 13:03

          Тогда он гений, и ему не нужен анализатор, а агромадный памятник. А потом, после изменения в зависимой библиотеке, переноса на другую платформу, и т.д. можно будет этот памятник снести.
          Ну или он просто так думает что у него один баг на 10 тысяч строк.


          1. Jef239
            05.12.2017 14:07

            Не гений, а просто embedчик. У такого написания кода есть свои минусы:

            • Почти нету слоя диагностики
            • Проще переписать код, чем найти баг.
            • Пишется раз в 10 медленней, с учетом отсутствия трат времени на отладку — примерно баш на баш.


            Но с переносом у него проблем нет.

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


        1. SirEdvin
          05.12.2017 13:51
          +2

          Он пишет на ассемблере, что ли?)


          1. Jef239
            05.12.2017 13:59

            Почти. Си как структурный ассемблер и задумывался.


        1. Whuthering
          05.12.2017 16:35
          +1

          10000 строк — слишком маленький проект, там даже тупо по статистике может действительно не быть багов. Реальный буст будет при кодовой базе на порядок или на два больше.


          1. Jef239
            05.12.2017 17:03

            Что такое проект, если не секрет? Драйвер — это проект? Подсистема или библиотека, лежащая в отдельном репозитарии — это проект? Системный слой (FreeRTOS + HAL + драйвера + обвязка) — это проект? Или проект — это все, что компилируется вместе в один бинарник? Или все, загружаемое в одну железку (3-4 процессора) — это один проект?

            Если первое — то там проекты (модули) по паре сотен строк. Если последнее — то ближе к полмиллиону.

            Сложно понять, что вы называете «проектом». :-) Embeded — оно такое…


            1. Lord_Ahriman
              06.12.2017 08:48
              +3

              Слушайте, по-моему, все, кто следит за этим блогом, да и просто те, кто встречает ваши комментарии, поняли, что вы занимаетесь embedded-системами (кстати говоря, несмотря на ваш вечный снобизм, это никак вас не выделяет из среды моих и ваших коллег). Надеюсь, вы понимаете, что у embedded своя специфика, и экстраполировать свой опыт в другие области несколько… некорректно?


              1. Whuthering
                06.12.2017 12:44
                +5

                Оставьте, данный товарищ давно уже засветился своим «вот мы такие прям молодцы эмбеддеры и асутпшники» втыкаемым везде к месту и вообще не к месту, причем с явной уверенностью, что кроме embedded и асутп в IT других сфер просто нет (или они не заслуживают внимания), а его личный опыт — это истина в последней инстанции для всех случаев. Спорить бесполезно, аргументы все равно будут проигнорированы.

                Ах, да, еще сей товарищ иногда активно бугуртится на негативное упоминание Delphi, при этом демонстрируя или полностью отсутствующие, или крайне устаревшие представления об альтернативных технологиях :)


              1. Jef239
                07.12.2017 05:16

                Мне кажется, что вы все перепутали. В отличие от коллеги, я не embedчик, 98-99 процентам моего кода все равно, где исполняться. Да и экстраполировал понятие «проект» не я, а Whuthering.

                Впрочем, могу и экстраполировать. Скажите Microsft Office это проект? Или проектом является Word? Или проект — это подсистема проверки орфографии? Или проект — это библиотека, используемая в нескольких программах? Или проект — это отдельный модуль c template, используемый в нескольких библиотеках?

                Как видите — ничего специфического для embeded тут нет.


          1. 0xd34df00d
            05.12.2017 23:38

            А это вообще от языка зависит. У меня ~3 тыщи строк на хаскеле развернулись в ~28 тыщ строк на плюсах. С boost spirit x3, темплейтами для сокращения кода и вот этим вот всем.


    1. YetAnotherSlava
      05.12.2017 21:31
      +1

      И за употребление слова «нубас» тоже.


  1. syscreat
    05.12.2017 13:54
    +2

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


    1. Jef239
      05.12.2017 19:49
      +1

      Что-то это мне напоминает

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

      Вообще очень полезно заменять слова PVS-Studio (или статический анализатор) словом молитва. Как правило, смысл при этом не меняется. :-)


  1. Jef239
    05.12.2017 13:57

    Ниша широка, и в ней замечательно помещается не только анализатор PVS-Studio,
    Что-то изменилось за 2.5 года?

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

    Главная ваша ошибка — очень мало кого интересует абстрактная польза. Интересует польза на рубль затрат. Путем терзания печени разработчиков при помощи веревочной петли и палки были примерно определены границы ниши для PVS-Studio:

    • Не меньше 250 тысяч строк в проекте
    • Не меньше 50 разработчиков


    процент ложных срабатываний у хороших анализаторов намного меньше, чем у компилятора.
    У хороших (то есть дорогих) — да. Тот же PVS-Studio на небольшом тесте вообще не дал ложных срабатываний. Зато бесплатный cppcheck не оправдывает время на анализ его предупреждений.

    Попробуйте скомпилировать свой код другим, еще не используемым ранее компилятором, и вы получите те же тысячи, а то и десятки тысяч предупреждений
    Если первый компилятор — не Visual Studio, то предупреждений будет намного меньше. После третьего компилятора — их количество (на четвертом, пятом и так далее) вообще стремится к нулю.

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

    Это очень глубокое заблуждение. Да, личный самолет — круче велосипеда. Но в булочную на нем ездить как-то неэффективно. Да, для личной странички можно заказать дизанй у Артемия Лебедева. Но будет ли это эффективно? Предупреждения компилятора бесплатны, ибо компилятор уже куплен. А PVS-Studio стоит килобаксы.

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

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

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

    Ваш собственный опыт показал, что ничего ужасного не произошло. :-)

    попробовать PVS-Studio очень просто.
    Если у вас Visual Studio или устроит пиратский вариант для open source — попробуйте. Если нет — то готовьтесь к неделе мучений. Документация у PVS-Studio в ужасном состоянии. Из 6 способов запуска, упомянутых в доке, работоспособными оказались только 2. Грубо говоря, документации нет, а есть набор статей, написанных на разных этапах развития программы. И перед запуском их нужно прочесть все, причем в правильном порядке. Тогда будет какое-то представление, что ещё работает, а что уже удалено за ненадобностью.

    По любым возникающим вопросам смело пишите в поддержку.
    Мы уже полгода ждем ответы. Если вы верите, что вам ответят быстрее — пишите. А если нет — то нет.


    1. ymuv
      05.12.2017 14:56

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

      Мы уже полгода ждем ответы. Если вы верите, что вам ответят быстрее — пишите. А если нет — то нет.

      Когда то писал с предложением добавить проверку что функция override-ит, ответили через несколько дней, сейчас вижу что проверка есть. Не корпоративный пользователь.


      1. Jef239
        05.12.2017 15:20

        Это отлично, что вам повезло. А вот нам, чтобы посмотреть PVS-Studio в деле потребовался тестовый ключ для линукс-версии. Полгода ждем. Как думаете, я его до пенсии дождусь? :-)

        Мне кажется, что не дождемся. Ибо наша компания дорастет до того размера, когда PVS-studio нам станет выгодным намного позже, чем я умру. То есть мы — не клиент для них. Потому и молчат, как партизаны. Самое интересное, что посылали запрос с незасвеченного мыла, не имеющего отношения к нашей фирме. Все равно не помогло.

        Не корпоративный пользователь.
        Вы потратили личные сотни килобаксов на PVS-Studio? Или это тот самый пиратский вариант использования?


        1. ymuv
          05.12.2017 15:25

          Не корпоративный пользователь.

          Вы потратили личные сотни килобаксов на PVS-Studio? Или это тот самый пиратский вариант использования?

          Не покупал, использовал для своего проекта (Open Source).


    1. 0xd34df00d
      05.12.2017 23:47
      +2

      Из 6 способов запуска, упомянутых в доке, работоспособными оказались только 2.

      Для протокола — с cmake'ом PVS отлично работает. Там где-то в ридмишке была команда для запуска поверх cmake ЕМНИП, я просто взял и запустил, и оно заработало.


      С Coverity было чуть сложнее, например, потому что я наркоман на gentoo и clang.


      Мы уже полгода ждем ответы. Если вы верите, что вам ответят быстрее — пишите. А если нет — то нет.

      Ну, когда я Андрея тут в личке и по почте доставал, он довольно быстро мне ключик для бетки скинул.


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


      Это, наверное, всё-таки естественный уровень для поддержки коммерческих продуктов. Когда я на IRC-канале clang кое-что спросил, мне там не очень вот помогли, это да.


      1. Jef239
        06.12.2017 06:34

        Для протокола — с cmake'ом PVS отлично работает.

        Угу, работает. Но с двумя известными ему препроцессорами. Нам на беду потребовался третий. :-)

        Это, наверное, всё-таки естественный уровень для поддержки коммерческих продуктов.

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


  1. tgz
    05.12.2017 17:28
    +2

    У программистов обычно никакой ответственности за говнокод нет, ну вылез там где-то null pointer, всем насрать. Запатчат и будут дальше говнокодить.


    1. qw1
      05.12.2017 20:04
      +1

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

      И никого не колышет, что написанный корректный код — по сути, доказанная теорема, и, внося, незначительные правки в задание, по хорошему, надо передоказывать (переосмысливать, перепроверять) всё написанное и времени на это нужно примерно столько же, как написать заново.

      Запатчить и дальше говнокодить — это то, что устраивает заказчиков по срокам и ценам.


      1. 0xd34df00d
        05.12.2017 23:51

        что написанный корректный код — по сути, доказанная теорема

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


  1. CodeRush
    05.12.2017 21:43

    Мужики, у вас версия для MacOS планируется хоть когда-нибудь? Там не должно быть слишком уж больших отличий от версии для Linux, по идее.


    1. Andrey2008 Автор
      05.12.2017 22:45

      Планируется.


  1. 0xd34df00d
    05.12.2017 23:33
    +1

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

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


    clang static-analyzer выдаёт прорву ложных срабатываний на моём коде. Например, «statement never executed» со стрелочкой на try, хотя одна из вызываемый внутри функций гарантированно кидает экзепшн при некоторых условиях. Или со стрелочкой на range-based for loop, хотя цикл тоже гарантированно выполняется. На кодовой базе одного моего проекта в ~560 kLOC такой ерунды — несколько сотен срабатываний.


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



    При этом Coverity охренительно умный. Coverity умеет видеть, например, что вы почти всегда проверяете возвращаемое значение у некоего неизвестного ему метода QFile::open (или QDomDocument::setContent, или QDialog::exec, неважно), и ругаться, когда вы этого не делаете, даже если в данном translation unit вы никогда ничего не проверяли. Считать ли это ложным срабатыванием, даже если вот прям здесь вы загружаете файл из ресурсов, а XML только что написали руками, и ошибок быть не может?


    А так как у вас всё-таки речь с позиций евангелистов PVS, то его тоже нельзя не упомянуть. Так вот, PVS существенно ближе к clang static-analyzer. На моей кодовой базе, опять же — где-то чуть меньше 1% true positives, остальное — false positives. И, увы, ряд false negatives, которые видит Coverity и иногда даже clang static-analyzer.


    Я вам уже давно статью обещал, и, собственно, основной вывод этой статьи — в моём опыте Coverity + clang static-analyzer покрывают строгое надмножество проблем, обнаруживаемых PVS'ом, при этом интерфейс у них дружелюбнее, да и с опенсорсом они работают лучше.


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

    Из более позднего тезиса более ранний не вытекает, нет там импликации.


    Я не настраиваю и не отключаю предупреждения компилятора. Наоборот, ищу, что бы подключить. Обновил clang, он научился определять, что явно захваченная в лямбду переменная не используется — это надо посмотреть и починить, либо пусть маячит как напоминание о недопиленной функциональности. Научился определять некоторые UB'шные битовые сдвиги — надо починить. Научился ругаться на отсутствие break в switch'ах — надо пройтись, порасставлять [[fallthrough]] или починить. Научился ругаться на неконсистентный override — надо починить. Научился ругаться на сравнения uint32_t < 0 — надо, ну, вы догадались.


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

    Более мощный статический анализатор мог бы баловаться, например, кроссTU-шным анализом, что сегодня делает только Coverity, и не делает ни clang static-analyzer, ни PVS.


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

    Увы, в моём опыте люди допускают в основном ошибки в логике, которые статический анализатор кода на C++ не поймает никогда, потому что тут уже нужны какие-нибудь формальные методы и пруверы теорем, в плюсах просто нет средств для достаточной выразительности.


    1. Andrey2008 Автор
      06.12.2017 00:26

      Я понимаю, что картина мира уже сформирована и все неудобные факты остаются вне восприятия. Тем не менее, всё равно вставлю свои 5 копеек.

      Я вам уже давно статью обещал, и, собственно, основной вывод этой статьи — в моём опыте Coverity + clang static-analyzer покрывают строгое надмножество проблем, обнаруживаемых PVS'ом
      Вот только, что интересно, это не мешает PVS-Studio вновь и вновь находить ошибки в LLVM. См. ссылки в статье. А ведь LLVM, проверяется регулярно Coverity + clang static-analyzer.


      1. 0xd34df00d
        06.12.2017 00:33

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

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

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


  1. gasizdat
    06.12.2017 09:22

    Форсинг стат анализа в целом и одного конкретного анализатора в частности, наталкивает на следующие мысли: статический анализ есть в любом зрелом компиляторе. Если его почему-то не хватает, то можно задуматься об использовании более одного компилятора под более чем одну платформу, битность, порядок байт, выравнивание и т.п. Т.е., например, берём Windows под x86, MacOS под x86_64, Linux под PowerPC и компилируем наше поделие несколькими разными компиляторами одновременно (например, VC, clang, gcc). В качестве параноидальной меры, выставляем максимальный уровень предупреждений (желательно только для своего кода) и treat warnings as errors. Получаем некислый поток ошибок, правим код, повторяем. В качестве бонуса получаем кроссплатформенный и кросспроцессорный код, с халявным многоуровневым статическим анализом под разные кейсы. При этом время тратится не на тонкую настройку анализатора (а по сути, на заметание вороха предупреждений под ковёр, в ложной надежде когда-нибудь к ним вернуться), а на написание переносимого кода, который потенциально намного лучше монетизируется.


    1. 0xd34df00d
      06.12.2017 10:22
      +3

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


    1. CodeRush
      06.12.2017 10:23
      +2

      Это все очень гладко на бумаге, но позволить себе подобное могут только те, у кого проекты либо очень маленькие, либо очень дорогие, либо на них сидит сотня человек и можно бросить десяток на доводку предупреждений многочисленных компиляторов.
      В реальности же абсолютное большинство проектов собирается для одной единственной ОС, одним единственным семейством компиляторов, без warnings-as-errors и прочего, и там от внедрения статического анализа (хоть какого-нибудь, не обязательно конкретно PVS-Studio) польза весьма существенная и доступна она практически сразу.
      Про предупреждения компиляторов: ну вот пока еще не один не смог предупредить меня, что у меня две функции имеют одинаковое тело, хотя задумывались разными, что у меня результат вызова функции не влияет на проверяемое значение, что у меня в условии продолжения цикла for используется оператор, в смысле &&, а это так не работает на самом деле, что у меня оптимизатор может удалить цикл ожидания на MMIO-регистре, потому что он не помечен как volatile, и вызов memset для затирания данных на стеке тоже может удалить, потому что он не влияет на наблюдаемое поведение.
      Понятно, что добрую половину всего вот этого можно получить, разобравшись с миллионом опций своего компилятора, но тут фишка в том, что сама по себе компиляция при этом с большой вероятностью сломается в стольких местах, что никто по доброй воле эти хитрые предупреждения больше никогда не включит.
      Внедрение хорошего статического анализатора туда, где его никогда не было, а код при этом писали на обычном C/C++ (а не на MISRA C с последующей верификацией) обычные люди (не Boeing/Airbus/NASA), за обычные деньги и при постоянного горящих сроках — оно сразу позволяет найти кучу ошибок, просто потому что на танцы с опциями компилятора ни у кого времени нет и никогда не будет.


      1. gasizdat
        06.12.2017 14:53

        Внедрение хорошего статического анализатора туда, где его никогда не было, а код при этом писали на обычном C/C++ (а не на MISRA C с последующей верификацией) обычные люди (не Boeing/Airbus/NASA), за обычные деньги и при постоянного горящих сроках — оно сразу позволяет найти кучу ошибок, просто потому что на танцы с опциями компилятора ни у кого времени нет и никогда не будет.

        Я не против статанализа. Скорее за него. Но если есть «халявный» способ и кроссплатформу написать и статанализ улучшить (за счет мультикомпиляции), то почему бы и нет.
        И потом, кто сказал, что использование статического анализатора могут позволить себе маленькие коллективы за небольшие деньги? Мой опыт говорит ровно об обратном. Перешагнуть требуемый порог в большом объеме легаси-кода очень и очень и очень-очень непросто и недешево. Есть вариант замести старые ошибки и предупреждения под ковер (это же рекомендует PVS для старых проектов), но это просто мусор под ковром и издевательство над идеей.
        Насчет MISRA C (и MISRA C++), то это ни от чего не страхует и ничего не гарантирует. (SIL3 и MISRA у нас тоже практикуются, но к счастью, не в проекте, над которым я работаю).

        ЗЫ
        Если что, то я о своем опыте ежедневной работы написал.


        1. Comdiv
          06.12.2017 21:01
          +1

          Насчет MISRA C (и MISRA C++), то это ни от чего не страхует и ничего не гарантирует
          Не гарантирует, но страхует. Насколько — зависит от обычного стиля и привычек программиста.


        1. Jef239
          07.12.2017 05:23

          И потом, кто сказал, что использование статического анализатора могут позволить себе маленькие коллективы за небольшие деньги? Мой опыт говорит ровно об обратном.
          Вот-вот, и я об этом. Статанализатор — хорошая штука, но экономически для малых команд выгодней другие меры,


    1. Andrey2008 Автор
      06.12.2017 10:32
      +1

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


      1. gasizdat
        06.12.2017 14:42

        Теоретически звучит красиво, но несовместимо с реальностью.

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

        Качество кода — оно такое, да.
        большие проекты, это не абстрактный конь код в вакууме, а активное использование больших сторонних библиотек,

        В проекте, с которым работаю я уже около 500 KSLOC (по метрике VisualStudio). И именно по этой причине у нас очень строгие правила насчет того, чтобы тянуть в проект сторонние библиотеки, отличные от stl.


        1. 0xd34df00d
          06.12.2017 19:19

          И именно по этой причине у нас очень строгие правила насчет того, чтобы тянуть в проект сторонние библиотеки, отличные от stl.

          Какие?

          У меня есть свой личный маленький проектик на >560 kSLOC одного лишь кода, без всяких ресурсов, и я как-то либерально к сторонним библиотекам подхожу и проблем от этого не сказать чтоб испытываю.


      1. Jef239
        07.12.2017 05:32

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


  1. Comdiv
    06.12.2017 12:59

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


  1. vlreshet
    06.12.2017 21:52

    Немного оффтоп, но всё же — на диплом магистра взял тему статического анализа js кода. Понятно что на довольно банальном уровне, диплом же а не докторская, но всё же. Кто-то может посоветовать какую-нибудь годную литературу на эту тематику? Свои велосипеды в голове давно придумал, хотелось бы узнать о готовых подходах