Незалежний огляд 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, на те воно і автоматичний. Але 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 Тайм-аут шлюзу.

Мова

Всі описи є російською, це чудово. Але посилання зі звіту завжди ведуть до англійської версії. Було б непогано мати можливість перемикати мову, щоб переглядати діагностику можна було відразу російською. В інтерфейсі такої можливості не знайшов.

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

Почнемо з того, що у двох команд (це 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 в іншому !!!) мають такий вигляд:

Незалежний огляд PVS-Studio (Linux, C++)

Не враховує багатопоточність

Багато хибнопозитивних спрацьовувань про нібито незмінні змінні або нескінченні цикли, при цьому робота з даними змінними відбувається з різних потоків, і якби це було не так, то модульні тести б не спрацьовували.

Незалежний огляд PVS-Studio (Linux, C++)

Втім, чи взагалі може таке врахувати статичний аналізатор? Не знаю.

Підсумки

PVS не знайшов жодної справжньої помилки у моїх відкритих проектах Вибух и Проксима, а також у робочому проекті, який я, зі зрозумілих причин, пред'явити не можу. Щоправда, варто мати на увазі, що деякі недоробки вже були відловлені та виправлені раніше за допомогою 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 або будь-які інші статичні аналізатори. Але я закликаю замислитися над тим, як так сталося, що статичний аналізатор постійно знаходить у вашому коді суттєві помилки.

Це лише слідство. Потрібно шукати та усувати причину.

Джерело: habr.com

Додати коментар або відгук