Независимый обзор PVS-Studio (Linux, C++)

    Увидел публикацию о том, что PVS таки научился анализировать под Линуксами, и решил попробовать на своих проектах. И вот что из этого получилось.



    Содержание


    1. Плюсы
    2. Минусы
    3. Итоги
    4. Послесловие


    Плюсы


    Отзывчивая поддержка


    Я запросил пробный ключ, в тот же день мне его прислали.


    Достаточно понятная документация


    Запустить анализатор удалось без особых проблем. Справка к консольным командам также имеется (хотя тут есть нарекания, см. раздел Минусы).


    Возможность многопоточного анализа


    У анализатора есть "стандартная" опция -j, позволяющая производить анализ параллельно в нескольких задачах. Это сильно экономит время.


    Хорошая визуализация


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


    Простая интеграция в сборку


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


    Хорошие описания диагностик


    Если генерировать вывод в режиме fullhtml, то у каждого сообщения есть ссылка на описание диагностики, с разъяснениями, примерами кода и дополнительными ссылками.



    Минусы


    Незнание анализатором языка C++


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


    Например, есть функция, возвращающая void:


    template <typename T>
    auto copy (const void * source, void * destination)
        ->
            std::enable_if_t
            <
                std::is_copy_constructible<T>::value
            >
    {
        new (destination) T(*static_cast<const T *>(source));
    }

    Да, ключевое слово auto может означать void, на то оно и auto. Но PVS выдал вот такие сообщения:


    dynamic_tuple_management.hpp:29:1: error: V591 Non-void function should return a value.
    dynamic_tuple_management.hpp:29:1: error: V2542 Function with a non-void return type should return a value from all exit paths.

    Очень тормознутый сайт


    Да, в веб-морде рядом с каждым сообщением есть ссылка на соответствующее описание диагностики с примерами. Но при нажатии на ссылку ждать приходится достаточно долго, а иногда бывает и 504 Gateway Time-out.


    Язык


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


    Неудобно работать с уровнями диагностик через консоль


    Начнём с того, что у двух используемых команд (это pvs-studio-analyzer и plog-converter) разные форматы задания диагностик.


    Справка к pvs-studio-analyzer гласит:


    -a [MODE], --analysis-mode [MODE]
        MODE defines the type of warnings:
        1 - 64-bit errors;
        2 - reserved;
        4 - General Analysis;
        8 - Micro-optimizations;
        16 - Customers Specific Requests;
        32 - MISRA.
        Modes can be combined by adding the values
        Default: 4

    Долго пытался понять, куда же нужно добавлять ("adding the values") ключи. Пытался перечислять через запятую:


    pvs-studio-analyzer analyze ... -a 1,4,16

    Пытался прописывать ключ несколько раз:


    pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16

    И только потом я догадался, что это же битовые маски! И нужно суммировать, а не добавлять значения. Например, чтобы получить общие диагностики, диагностики по микрооптимизациям и MISRA, нужно их просуммировать (4 + 8 + 32 = 44):


    pvs-studio-analyzer analyze ... -a 44

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


    Кроме того, есть ещё утилита plog-converter, которая генерирует человекочитаемую информацию о статическом анализе. У неё другие заморочки.


    Справка к программе plog-converter сообщает:


    -a, --analyzer            Specifies analyzer(s) and level(s) to be
                              used for filtering, i.e.
                              'GA:1,2;64:1;OP:1,2,3;CS:1;MISRA:1,2'
                              Default: GA:1,2

    Здесь появились какие-то "уровни", которых раньше нигде не было, и в документации я про них тоже ничего не нашёл.


    В общем, непонятно. Поэтому я всё выставлял по максимуму.


    Куча бестолковой ругани на Catch


    В двух из трёх проектов, которые я анализировал, используется библиотека модульного тестирования Catch2. И львиная доля сообщений (!!! 90 из 138 в одном и 297 из 344 в другом !!!) имеют следующий вид:


    Catch2


    Не учитывает многопоточность


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


    Многопоточность


    Впрочем, может ли вообще такое учесть статический анализатор? Не знаю.



    Итоги


    PVS не нашёл ни одной настоящей ошибки в моих открытых проектах Burst и Proxima, а также в рабочем проекте, который я, по понятным причинам, предъявить не могу. Правда, стоит иметь в виду, что кое-какие недоработки уже были отловлены и исправлены ранее с помощью Cppcheck и scan-build.


    В целом впечатление от всех этих анализаторов примерно одинаковое: да, что-то они ловят, иногда даже что-то важное, но в целом компилятора хватает.


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


    Поэтому беру на себя смелость дать несколько советов о том, как писать на языке C++ так, чтобы не отстреливать никому ноги и не огребать граблями по лбу.


    Используйте диагностики компилятора по максимуму


    Наша команда использует (и вам советует) следующие опции компиляции:


    -Werror
    
    -Wall
    -Wextra
    -Wpedantic
    
    -Wcast-align
    -Wcast-qual
    -Wconversion
    -Wctor-dtor-privacy
    -Wenum-compare
    -Wfloat-equal
    -Wnon-virtual-dtor
    -Wold-style-cast
    -Woverloaded-virtual
    -Wredundant-decls
    -Wsign-conversion
    -Wsign-promo

    Включите их в своём проекте, узнаете много нового о своём коде.


    Придерживайтесь стандарта


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


    Придерживайтесь стандартной семантики операций


    Сложение должно быть сложением, умножение — умножением, вызов функции — вызовом функции, копирование должно копировать, перенос — переносить, контейнер должен быть итерируем, итератор должен иметь продвижение ++ и разыменование *. И так далее, и так далее.


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


    Пишите совместимый код


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


    Не стесняйтесь подсматривать в интерфейсы STL и Boost. За редкими исключениями там вы увидите достойный пример для подражания.


    Используйте по максимуму открытые инструменты


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


    Подробнее об этом можно почитать в моей недавней публикации.



    Послесловие


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


    Это лишь следствие. Нужно искать и устранять причину.

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 70

      –23
      Долго пытался понять, куда же нужно добавлять («adding the values») ключи
      если последовательность цифр 1,2,4,8,16,32 в режимах вас не натолкнула на мысль как использовать эти флаги, возможно вы рано взялись за статический анализ
        +2
        В протоколе общения с фискальным принтером есть что-то вроде такого ряда значений:
        1, 2, 4, 8, 16, 17, 18, 19…
        Поэтому не стоит полагаться на то, что что-то похоже на битовый ряд.
          0
          ваш пример вообще не похож на битовый ряд. хотя насчёт самого протокола, без документации ничего сказать нельзя. вдруг там уже посчитали за вас 16+1, 16+2…
            +1

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

          0
          Возможно, проблема в том что вы предпочитаете гадать, догадываться или угадывать вместо того чтобы разобраться и использовать? Мне например не хочется гадать о том что нужно делать, потому что мне надо выполнить задачу.
          –9
          Вот пока оно на таких примитивных примерах не перестанет видеть 4 ошибки (2 из которых помечает critical) на любых C-проектах оно бесполезно:
          i32 bxi_memcmp(const void * p1, const void * p2, u32 cnt) {
              const u8   * p1_u8 = p1;
              const u8   * p2_u8 = p2;
              const pu_t * p1_pt = p1;
              const pu_t * p2_pt = p2;
          
              if (p1_u8 == p2_u8)
                  return 0;
              if (p1_u8 == NULL)
                  return *p2_u8; // Кое-кто думает, что тут разыменовывается NULL. Видимо кто-то просто пытается найти if (p2_u8 == NULL)
              if (p2_u8 == NULL)
                  return *p1_u8; // То же самое. На каждую строку два предупреждения.
              if (!cnt)
                  return 0;
            +7

            В оправдание статических анализаторов должен сказать, что:


            1. Ложноположительный срабатывания не делают их бесполезными. Главное, чтобы при этом были и истинноположительные.
            2. Данные код действительно можно было бы записать посимпатичнее. Хотя и так корректно.
              0
              Данные код действительно можно было бы записать посимпатичнее.


              Только проверяя на каждый чих на NULL, что совершенно излишне:
              if (p1_u8 == NULL && p2_u8 == NULL)
                      return 0;
              if (p1_u8 == p2_u8)
                      return 0;
              if (p1_u8 == NULL && p2_u8 != NULL)
                      return *p2_u8; // черт его знает, хватит ли текущей проверки PVS или самое первое условие все равно надо оставить
              if (p2_u8 == NULL && p1_u8 != NULL)
                      return *p1_u8;
              

              Зачем, если правая часть никогда не выполнится?

              UPD, плюс надо еще вставить все равно проверку на p1 == p2, потому что that's what memcmp do
                0
                А так PVS будет ругаться?
                i32 bxi_memcmp(const void * p1, const void * p2, u32 cnt)
                {
                    if (!cnt || (p1 == p2))
                        return 0;
                    else if (p1 == NULL)
                        return 1;
                    else if (p2 == NULL)
                        return -1;
                    else {
                        const u8   * p1_u8 = p1;
                        const u8   * p2_u8 = p2;
                        const pu_t * p1_pt = p1;
                        const pu_t * p2_pt = p2;
                        ..........
                    }
                }
                
                  0
                      else if (p1 == NULL)
                          return 1;
                      else if (p2 == NULL)
                          return -1;

                  Тут не совсем то, что нужно по поведению. Формально соответствует ману, но не соответствует поведению glibc.
                    0
                    Я не понимаю return *p1_u8/return *p2_u8
                      0
                      Возвращается значение разницы. Формально надо во втором случае еще "-" добавить, но так как использовать сравнение по знаку никогда не требуется, то мы его опустили.
                        0
                        Понял. Смутило memcmp в названии функции.
                    0
                    Что-то совсем уже сонный. Конечно
                    ...
                    if (p1 == NULL)
                      return -1;
                    else if (p2 == NULL)
                      return 1;
                    ...
                  +3
                  Ложноположительный срабатывания не делают их бесполезными. Главное, чтобы при этом были и истинноположительные.
                  Делают. Получишь 1000 ложных предупреждений и пропустишь важных 2
                    0

                    Размывают — это да. Но с формальной точки зрения бесполезными таки не делают.


                    Не думаю, что у нас здесь есть спор. Мне просто "обидно стало" за статические анализаторы и я решил их "позащищать".

                      0
                      Хорошая идея. Берешь 3 разных, и по пересекающимся смотришь. Или компилятор в стрикт + 2 линтера…
                      Да сложно там все, робот может и не дотумкать
                        0

                        Пересекающихся очень мало. Все о разном поют.

                  +5
                  Ну вообще-то это не «примитивный пример» ни разу. Чтобы понять, что в этом коде нет ошибки — нужен data flow analysis… и, в общем, не самый нетривиальный.

                  То есть да, в идеале можно было бы хотеть, чтобы из того факта, что два указателя неравны PVS-Studio выводила следствие, что хотя бы один из указателей — не NULL, но… вы действительно пишите код, где подобные трюки используются часто?
                    0
                    вы действительно пишите код, где подобные трюки используются часто?
                    Выше я привел пример, как этот код должен быть записан иначе. Он менее оптимизирован, в нем есть проверки которые никогда не выполнятся и он замыливает глаз бесконечными сравнениями с NULL.
                      +1
                      К вашему коду, претензий у меня нет. Я задавал совсем другой вопрос: насколько часто используются подобные трюки в вашем коде.

                      Потому что если у вас таких функций одна-две… ну отключите вы эти предупреждения и всё.

                      А вот если ваш код весь из подобных трюков состоит… то тут уже возникает вопрос: что ж вы такое пишите и почему вы считаете, это — «типичный C»…
                        0
                        насколько часто используются подобные трюки в вашем коде.

                        Только критичные места. Есть даже асм вставка для филла памяти интом а не чаром. Просто тут такое дело. Если вы изначально взяли инструментом си, а не, скажем, скалу, то ваш код ДОЛЖЕН быть быстрым, максимально производительным и заточенным в первую очередь для машины, а не человека. Иначе вы выбрали не тот инструмент для задачи.

                        Простой пример:
                        Есть бек1, который общается с устройствами битами\байтами на больших скоростях и по разным протоколам. Устройств под сотню. Есть бек2, которому бек1 передает данные в унифицированном виде скажем раз в 5-15 секунд (при этом сам бек1 может получать мегабайты информации в секунду от одного устройства). И есть фронт, которому бек2 говорит что рисовать.
                        Так вот. Вы же не будете брать Scala на роль бек1, верно? Вы возьмете что-то, что будет быстро разбирать протоколы, парсить данные и переформатировать сериализированные данные в какой-нибудь JSON\DBUS. Потому что скорее всего (был опыт) JAVA-based на подобных задачах будет либо очень тормозить и не успевать все обработать, либо кушать 25 ГБ памяти (был скрин, но я проесеял). Поэтому скорее всего на роль бек1 вы возьмете с/с++/RUST/что там еще сегодня модно. Главная задача бек1 — быть максимально оптимизированным. А это автоматически означает подобные «трюки» в коде.
                        Понятно, что они будут в критически важных функциях, но они будут.
                          +1
                          Понятно, что они будут в критически важных функциях, но они будут.
                          Если они будут в небольшом количестве функций, то вы можете там отключить предупреждения и всё.

                          Тот же Rust, который весь построен вокруг «гарантированной безопасности» имеет аж целое ключевое слово unsafe для таких целей… так почему вы считаете что весь ваш код, 100% должен проходить все чеки без каких-либо замечаний через PVS-Studio?
                            +2
                            Посмею продолжить мысль предыдущего оратора.
                            Отключение диагностики должно означать примерно следующее: «Я знаю, что я делаю, больше прошу не беспокоить.»
                            +2
                            Есть даже асм вставка для филла памяти интом а не чаром.
                            А зачем? Есть подозрение, что эффективнее использовать обыкновенный memset. Подобные функции настолько оптимизированы, что сложно самостоятельно написать что-то более быстрое. Более того, игры в преждевременную оптимизацию, могут оборачиваться ошибкой. Причем, эта оптимизация совершенно лишняя (пример).

                            P.S. Наверное это странно слышать от человека, который выступит на следующей C++Russia с докладом «Преждевременная оптимизация — зло! Да здравствует преждевременная оптимизация!». Т.е. я совсем не против преждевременной оптимизации. Но у меня есть сильное подозрение, что часто необходимость такой оптимизации излишне завышается. И многие только думают, что они занимаются оптимизацией, но по факту только зря пишут более длинный, сложный и запутанный код, чем было можно.
                              –6
                              Есть даже асм вставка для филла памяти интом а не чаром.

                              А зачем? Есть подозрение, что эффективнее использовать обыкновенный memset.


                              Не хотел бы я попасть на доклад по С++ к человеку, который не знает, что memset заполняет все char'ом, а не int'ом.
                                +2
                                memset из glibc и newlib заполняет почти всю память int'ом, а вот невыровненные кусочки в начале и в конце(если есть) пишет через char
                                  –4
                                  Речь про значение, а не то, КАК она заполняет. Попробуйте заполнить memset'ом память значением 0xaabbccdd.
                      +2
                      Это начинает походить на троллинг. Как 2 года нашли это ложное срабатывание, так с ним везде и ходите :). Не спортивно. Да, у PVS-Studio есть недостатки в анализе потока данных, и мы постепенно их исправляем. Конкретно этот случай намного сложнее, чем кажется на первый взгляд. Когда ни будь, исправим и его.
                        +1
                        Как 2 года нашли это ложное срабатывание, так с ним везде и ходите

                        Ну то есть вы за два года так и не смогли это исправить? Зато цену подняли в N раз и продолжаете посылать в пешее всех, кто не компания с доходом от нескольких лямов в год.
                          +1
                          Существует такая штука, как приоритет задач. Можно удовлетворить анонима с linux.org.ru. А можно реализовывать пожелания клиентов и потенциальных клиентов, выпустить версию для Java, поддержать классификацию CWE и CERT, добавить поддержку стандарта MISRA, интегрироваться с Travis CI.
                            0
                            Можно удовлетворить анонима с linux.org.ru.


                            Какая разница, кто зарепортил баг, если до его решения ваша поделка просто проверяет наличие if (a == NULL), создавая несколько critical false-positive в случае его отсутствия?

                            P.S. Насчет «анонима». Мне напомнить, как вы плодили там виртуалов и как вас там 3 (или уже больше?) раз банили за спам?
                              0
                              Да у меня там 100500 виртуалов. Как и на Хабре. Вот видите, как ловко я эту статью написал.
                              Для тех, кто не понял сарказм
                              Я имел в виду отсылку к этому комментарию. Популярность PVS-Studio растёт и на него начинают писать и упоминать совершенно разные люди. Как здесь, так и на linux.org.ru. Но там, любое упоминание PVS-Studio расценивается как происки команды PVS-Studio. Это так забавно наблюдать.
                                –2
                                Но там, любое упоминание PVS-Studio расценивается как происки команды PVS-Studio

                                Нет. Там вас не любят за нарушение правил форума, за спам, за оскорбление участников форума, за несоответствие тематике форума, за отказ предоставления модифицированных исходников GPL проектов, которые вы использовали для анализа, за клоунаду и неприкрытую рекламу.
                      +14
                      Вообще про многопоточность — было бы интересно тоже примеры кода увидеть. Потому что разговоры про «модульные тесты» в контексте многопточности вызывают только смех.

                      Вы про то, что процессор может переставлять операции не забыли? Какие барьеры используются чтобы не было проблем? TSAN молчит?

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

                      То же самое с auto, кстати: довод, что это не противоречит стандарту — очень слабый. Если бы противоречило — код бы просто не скомпилировался. Описывать функцию, которая ничего не возвращает как auto — это путать читателя, как минимум.

                      P.S. А вообще — статья хорошая. Показывает, по крайней мере, почему PVS Studio имеет смысл продавать именно так, как она продаётся. Потому что вы совершили почти все «ошибки новичка», про которые тут недавно писали. То есть и любой другой человек «с улицы», скорее всего, их совершит…
                        +5
                        разговоры про «модульные тесты» в контексте многопточности вызывают только смех.

                        Ну посмейтесь. ¯\_(ツ)_/¯


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

                        Я специально предъявил анализируемый код. Каждый может взять и проверить.


                        То же самое с auto, кстати: довод, что это не противоречит стандарту — очень слабый. Если бы противоречило — код бы просто не скомпилировался. Описывать функцию, которая ничего не возвращает как auto — это путать читателя, как минимум.

                        Слово auto вместе со стрелочкой -> после аргументов функции означает, что тип будет указан после этой самой стрелочки. И это может быть void. Путаться тут негде.


                        P.S. А вообще — статья хорошая. Показывает, по крайней мере, почему PVS Studio имеет смысл продавать именно так, как она продаётся. Потому что вы совершили почти все «ошибки новичка», про которые тут недавно писали. То есть и любой другой человек «с улицы», скорее всего, их совершит…

                        Я статическими анализаторами пользуюсь регулярно. О чём упоминал в публикации.

                          0
                          Слово auto вместе со стрелочкой -> после аргументов функции означает, что тип будет указан после этой самой стрелочки. И это может быть void. Путаться тут негде.

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

                          template <typename T>
                          std::enable_if_t<std::is_copy_constructible<T>::value> copy (const void * source, void * destination)
                          {
                              new (destination) T(*static_cast<const T *>(source));
                          }
                          


                          и ничего бы не изменилось. Но я так понимаю что у вас просто стиль видимо такой принят для единообразия или еще для чего.
                            +2

                            Лишний или не лишний — дело вкуса.


                            Так или иначе, анализатор работает неправильно.

                            +1

                            Добавил скриншот в раздел про многопоточность.
                            Сам тест находится здесь: https://gitlab.com/star-system/proxima/blob/master/test/proxima/thread/thread_pool.cpp#L94

                              0
                              Интересно, а если переписать без auto, типа:

                              std::atomic<bool> stopped(false);

                              будет так же ругаться?
                                +2

                                Действительно, меньше ругается:


                                Выходит, у него ещё больше проблем с пониманием языка C++.

                                  0
                                  Ну у него видимо проблемы с выводом типов. Когда он все-таки видит что там std::atomic, то шелуха выкидывается и остается только в принципе довольно логичное предупреждение про infinite loop. Может если для p аналогичным образом тоже убрать auto, то у него даже достанет мощи заглянуть в реализацию p.post() и p.stop() и остальные предупреждения тоже уберутся :)
                                    +1
                                    Может если для p аналогичным образом тоже убрать auto, то у него даже достанет мощи заглянуть в реализацию p.post() и остальные предупреждения тоже уберутся :)

                                    Нет, не достало, к сожалению.

                                      0
                                      Полезнее yield добавить, если вам так уж приспичило спинлоки руками реализовывать.

                                      Хотя, condvar — ещё лучше. Они, собственно, для подобных случаев и предназначены.
                              0
                              Вы про то, что процессор может переставлять операции не забыли? Какие барьеры используются чтобы не было проблем?

                              Судя по скрину, seq_cst. Но это на самом деле неважно — в скорое появление анализаторов, эффективно различающих эффекты от замены seq_cst на relaxed, я не верю.


                              А вот tsan в моем опыте с атомиками работает отвратительно.

                              +2

                              Попробуйте coverity scan, в моем опыте он на голову выше pvs и scan-build вместе взятых.

                              • UFO just landed and posted this here
                                  +1

                                  Решил попробовать хвалёный coverity scan.


                                  Итоги: на моём проекте он не заработал, ибо забуксовал на файле boost/type_index/ctti_type_index.hpp, завис и отожрал всю память.


                                  Написал в поддержку, уже больше недели нет ответа.


                                  Вот так

                                  Пара-пара-пам!

                                    +1
                                    И не ответят. Там и на корпоративном уроне есть эта проблема, что достаточно критично для текущих и уже бывших клиентов этого анализатора.
                                • UFO just landed and posted this here
                                    –18

                                    Опять про этот PVS? Не, все понимаю: реклама, регулярность… Но если честно, то уже подзадолбало видеть материалы про него через раз в списках статей, имейте совесть

                                      +8

                                      Статью не читай, сразу комментируй.


                                      Да, я рекламирую PVS, угу.

                                        +4
                                        Феномен Баадера-Майнхофа)
                                        0
                                        Слегка оффтопик вопрос: кто-нибудь использует рекомендации github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md и связанную с ними библиотеку github.com/Microsoft/GSL? Как это сочетается с Qt?

                                        Я как-то застрял на 14 стандарте и о данных вещах узнал только из предупреждений clang-tidy.
                                          +12
                                          Большое спасибо за статью. Несколько комментариев. Комментарии не с целью сказать, что автор в чём-то не прав. Такие статьи именно и прекрасны тем, что показывают восприятие стороннего человека нашим продуктом, выявляют его недостатки и неудачные решения в интерфейсе, которые сбивают с толку. Мы благодарны за обстоятельную заметку и подумаем над некоторыми моментами.

                                          Например, есть функция, возвращающая void:
                                          Да, недоработка. Предупреждение V591 разрабатывалось очень давно и оказалось не готово к такому коду. Исправим. Тяжело предвидеть как каждая новая возможность языка может отразиться на ранее разработанных диагностиках. Как быть с этой проблемой пока не знаем. Правим по факту, когда выявляются подобные ложные срабатывания.

                                          Что касается V2542, то очень прошу полностью выключить MISRA. Этот набор диагностик очень специализирован и противопоказан для обыкновенных прикладных проектов. Будет сплошной шум, которые будет только сбивать. Подробнее про это я писал здесь.

                                          Очень тормознутый сайт
                                          Эффект демонстрации :). Именно на этой недели сайт плющит и мы разбираемся с источником проблемы. Специально что-то делать для быстрого доступа к описанию смысла нет. Починим и будет как всегда всё ok. Просим прощение за временно доставленные неудобства.

                                          Куча бестолковой ругани на Catch
                                          Нужна минимальная настройка анализатора. Можно поступить по разному. Один из вариантов, в одном из глобальных заголовочных файлов написать комментарий //-V:REQUIRE:521. Лучше его написать рядом с объявлением самого этого макроса, но залазать в код сторонней библиотеки, это конечно плохое решение. Документация по борьбе с предупреждениями в макросах здесь.

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

                                          Ещё раз спасибо за проделанную работу.
                                            +3
                                            Нужна минимальная настройка анализатора

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


                                            P.S. Спасибо за адекватную реакцию.

                                            +2
                                            Я вчера тоже, после статьи, попросил ключик и запустил на своём проекте. Выдало 75 варнингов, где-то половину перелопатил между делом… Большая часть сообщений некритична, вроде код двух кейсов совпадает, можно объединить или не все переменные инициализируются конструктором… Но нашёл несколько весьма интересных ошибок, вероятность срабатывания которых весьма мала, но существует… За это ему спасибо :)

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

                                            Хотел посмотреть сколько стоит инструмент, но на сайте предлагают послать запрос. От этого несколько коробит, создаётся ощущение, что хотят содрать три шкуры )))
                                              +1
                                              > приятно был удивлён тем, что ошибок практически нет.
                                              Не забывайте про эффект, что ошибки могли быть поправлены более дорогими способами :).

                                              Для индивидуальных проектов: Бесплатные варианты лицензирования PVS-Studio.
                                                +2
                                                Скорее это эффект от любви к функциональным и интеграционным тестам :)

                                                За ссылку спасибо, буду иметь в виду.

                                                  0

                                                  Проект достоин внимания. Использовал на практике совместно с cppcheck.
                                                  Но так как коммерческий софт, решено не садиться на иглу, а использовать только открытые ПО.
                                                  Использую cppcheck и максимальные уведомления от компилятора. В итоге получается, в целом, неплохо.

                                                0
                                                Сам я джавист, с потоками напрямую работал последний раз в университете, поэтому у меня, возможно, глупый вопрос: разве
                                                while(not stopped);
                                                не будет жрать процессор со страшной силой? Для этого же есть как-раз все эти прерывания, нотифайи и мьютексы?
                                                  0
                                                  не будет жрать процессор со страшной силой

                                                  Будет. Но не в модульных тестах, которые все вместе отрабатывают менее чем за 0,1 с.


                                                  Для этого же есть как-раз все эти прерывания, нотифайи и мьютексы?

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

                                                    0
                                                    Иногда это вполне оправданно, особенно если код пишется под микроконтроллеры, скажем под какую-нибудь систему ПВО. Где очень критично реал тайм поведение.
                                                      –3
                                                      Дада, а потом начинаются стенания мол «Почему ваше PVO ничего не ловит!»
                                                    +2
                                                    Напоследок подчеркну, что я не призываю не использовать PVS или какие-либо другие статические анализаторы. Но я призываю задуматься о том, как так вышло, что статический анализатор постоянно находит в вашем коде существенные ошибки.

                                                    Это лишь следствие. Нужно искать и устранять причину.


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

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

                                                    IMHO взял за правило добавлять всевозможные линтеры и статические анализаторы, которые бы старались найти косяки вот прям сразу в CI. Становится легче жить после такого )
                                                      +3
                                                      Вот да, как оценка проекта, который тебе отдают на поддержку, очень даже хорошо PVS работает. Грубо, если он там найдет 1000+ high предупреждений и 5000+ medium, то ничего хорошего это не предвещает :)
                                                      0
                                                      Я работаю под Линуксом — пишу код на С++ в qtcreator. Не увидел «фишки» от использования PVS — статический анализ кода не хуже, чем описано в статье, и бесплатный qtcreator умеет.
                                                        0
                                                        Автор статьи не ставил задачи сделать обзор фишек. Чтобы подробнее узнать о возможностях лучше посетить наш сайт.

                                                        А по поводу того, что qtcreator умеет всё тоже самое что PVS-Studio… Вот такая в том году заметка была "Третья проверка Qt 5 с помощью PVS-Studio". Я понимаю, что Qt и qtcreator это не одно и тоже. Но если в qtcreator так всё хорошо, то откуда все эти ошибки в Qt? :) Даже поверхностно просматривая отчёт, я выписал почти 100 ошибок.
                                                          +1
                                                          «Всё хорошо» вряд ли где то есть на 100%. Я только имею ввиду ЖЕЛАНИЕ и ВОЗМОЖНОСТЬ писать качественный код. При наличии желания такую возможность могут предоставить и свободные инструменты.

                                                          А что касается статьи, то начиная её читать я ожидал найти в ней информацию, которая убедит меня в том, что за деньги PVS-Studio предоставит больше возможностей чем другие инструменты. Увы.
                                                            0
                                                            • Быстрая и качественная поддержка.
                                                            • Автоматический анализ отдельных файлов после их перекомпиляции.
                                                            • Удобная и простая интеграция с Visual Studio 2010-2019.
                                                            • Удобная online-справка по всем диагностикам, которая доступна и из программы, и на сайте, а также документация в .pdf одним файлом.
                                                            • Сохранение и загрузка результатов анализа: можно ночью проверить код, сохранить результаты, а утром загрузить их и смотреть.
                                                            • Возможность сохранить результаты анализа в формате HTML с полной навигацией по коду.
                                                            • Запуск из командной строки для проверки всего решения: позволяет интегрировать PVS-Studio в ночные сборки, чтобы утром у всех был свежий лог.
                                                            • Отличная масштабируемость! Поддержка многоядерных и многопроцессорных систем с настройкой количества используемых ядер; поддержка IncrediBuild.
                                                            • Mark as False Alarm – разметка в коде, чтобы не ругаться конкретной диагностикой в конкретном фрагменте файла.
                                                            • Интерактивная фильтрация результатов анализа (лога) в окне PVS-Studio: по коду диагностики, по имени файла, по включению слова в текст диагностики.
                                                            • Утилита BlameNotifier. Инструмент позволяет рассылать письма разработчикам об ошибках, которые PVS-Studio нашел во время ночного прогона.
                                                            • Большое количество вариантов интеграции в проекты, разрабатываемые под Linux и macOS.
                                                            • Mass Suppression – позволяет подавить все старые сообщения, чтобы анализатор выдавал 0 срабатываний. К подавленным сообщениям всегда можно вернуться позже. Возможность безболезненно внедрить PVS-Studio в существующий процесс разработки и сфокусироваться на ошибках только в новом коде.
                                                            • Автоматическая проверка на наличие новых версий PVS-Studio (как при работе в IDE, так и при ночных сборках).
                                                            • Использование относительных путей в файлах отчета для возможности переноса отчета на другую машину.
                                                            • Отслеживание компиляции (Compiler Monitoring) – проверка проектов, у которых нет файлов Visual Studio (.sln/.vcxproj), без необходимости проводить интеграцию со сборочной системой; при необходимости, можно провести прямую интеграцию анализатора в любую сборочную систему.
                                                            • pvs-studio-analyzer – утилита для отслеживания компиляции (Compiler Monitoring) на Linux.
                                                            • Возможность исключить из анализа файлы по имени, папке или маске; возможность проверять файлы, модифицированные за последние N дней.
                                                            • Интеграция с SonarQube. Это открытая платформа для обеспечения непрерывного контроля качества исходного кода.

                                                      Only users with full accounts can post comments. Log in, please.