Niezależna recenzja PVS-Studio (Linux, C++)

Zobaczyłem publikację, którą PVS nauczył się analizować pod Linuksem, i zdecydowałem się wypróbować ją w moich własnych projektach. I oto co z tego wyszło.


Zawartość

  1. Plusy
  2. Wady
  3. Wyniki
  4. Posłowie

Plusy

Responsywne wsparcie

Poprosiłem o klucz próbny i wysłali mi go tego samego dnia.

Dość przejrzysta dokumentacja

Udało nam się uruchomić analizator bez żadnych problemów. Dostępna jest także pomoc dotycząca poleceń konsoli (chociaż są tu pewne zastrzeżenia, patrz sekcja Wady).

Możliwość analizy wielowątkowej

Analizator posiada opcję „standardową”. -j, co pozwala na prowadzenie analizy równolegle w kilku zadaniach. Oszczędza to dużo czasu.

Dobra wizualizacja

Wiele różnych formatów wyjściowych, od tekstu po mały kaganiec internetowy. Interfejs sieciowy jest wygodny, zwięzły, zawiera podpowiedzi przy liniach kodu i linki do opisów diagnostycznych.

Łatwa integracja z montażem

Cała dokumentacja znajduje się na ich stronie internetowej, mogę tylko powiedzieć, że jeśli Twój projekt jest zbudowany przy użyciu CMake, wszystko jest bardzo proste.

Dobre opisy diagnostyczne

Jeśli generujesz dane wyjściowe w mode fullhtml, wtedy każda wiadomość zawiera link do opisu diagnostycznego z objaśnieniami, przykładami kodu i dodatkowymi linkami.

Wady

Nieznajomość języka C++ przez analizatora

Niestety, PVS czasami popełnia błędy składniowe i generuje fałszywie pozytywne komunikaty, gdy kod jest całkowicie poprawny.

Na przykład istnieje funkcja, która zwraca 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));
}

Tak, słowo kluczowe auto Może oznaczać void, po to właśnie jest samochód. Ale PVS przedstawiło następujące komunikaty:

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.

Bardzo powolna strona

Tak, w interfejsie internetowym obok każdego komunikatu znajduje się link do odpowiedniego opisu diagnostycznego z przykładami. Ale kiedy klikniesz na link, musisz poczekać dość długo i czasami tak się dzieje 504 Gateway Time-out.

język

Wszystkie opisy są w języku rosyjskim, co jest świetne. Jednak linki w raporcie zawsze prowadzą do wersji angielskiej. Byłoby miło móc zmienić język, aby móc od razu przeglądać diagnostykę po rosyjsku. W interfejsie nie znalazłem takiej opcji.

Praca z poziomami diagnostycznymi za pośrednictwem konsoli jest niewygodna

Zacznijmy od tego, że dwa użyte polecenia (this pvs-studio-analyzer и plog-converter) różne formaty określania diagnostyki.

Pomoc dla pvs-studio-analyzer brzmi:

-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

Długo zastanawiałem się, dokąd pójść dodaj („dodawanie wartości”). Próbowałem je wymienić oddzielonymi przecinkami:

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

Próbowałem zarejestrować klucz kilka razy:

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

I dopiero wtedy zdałem sobie sprawę, że to były maski bitowe! I potrzebujesz podsumowaćI nie dodaj znaczenia. Przykładowo, aby uzyskać diagnostykę ogólną, diagnostykę dla mikrooptymalizacji i MISRA należy je zsumować (4 + 8 + 32 = 44):

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

Używanie masek bitowych w interfejsach użytkownika jest ogólnie złą formą. Wszystko to można podsumować wewnętrznie i ustawić zestaw flag dla użytkownika.

Ponadto istnieje również narzędzie plog-converter, który generuje czytelne dla człowieka informacje analizy statycznej. Ona ma inne problemy.

Pomoc dla programu plog-converter raporty:

-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

Pojawiły się tutaj pewne „poziomy”, których wcześniej nie było, a w dokumentacji też nic na ten temat nie znalazłem.

Generalnie nie jest to jasne. Dlatego ustawiłem wszystko na maksimum.

Mnóstwo głupich przekleństw na temat Catcha

Dwa z trzech analizowanych przeze mnie projektów korzystają z biblioteki testów jednostkowych Catch2. A lwia część przekazów (!!! 90 ze 138 w jednym i 297 z 344 w drugim!!!) ma następującą postać:

Niezależna recenzja PVS-Studio (Linux, C++)

Nie uwzględnia wielowątkowości

Istnieje wiele fałszywych alarmów dotyczących rzekomo niezmiennych zmiennych lub nieskończonych pętli, podczas gdy praca z tymi zmiennymi odbywa się z różnych wątków, a gdyby tak nie było, testy jednostkowe nie zadziałałyby.

Niezależna recenzja PVS-Studio (Linux, C++)

Czy jednak analizator statyczny może w ogóle to uwzględnić? Nie wiem.

Wyniki

PVS nie znalazł żadnych poważnych błędów w moich projektach open source Burst и Proxima, a także w wersji roboczej, której z oczywistych względów nie mogę przedstawić. To prawda, warto mieć na uwadze, że pewne niedociągnięcia zostały już wyłapane i skorygowane podczas wcześniejszego użytkowania Kontrola Cpp и scan-build.

Ogólnie wrażenie ze wszystkich tych analizatorów jest w przybliżeniu takie samo: tak, wyłapują coś, czasem nawet coś ważnego, ale ogólnie kompilator wystarczy.

Możliwe jest (i osobiście lubię tak myśleć), że nasz zespół stosuje praktyki tworzenia oprogramowania, które pozwalają nam wygenerować minimalną ilość gównianego kodu. Lepiej nie stwarzać problemów, niż bohatersko je przezwyciężać.

Dlatego pozwolę sobie doradzić, jak pisać w C++ tak, aby nikomu nie odstrzelić nogi i nie uderzyć grabiami w czoło.

Wykorzystaj w pełni diagnostykę kompilatora

Nasz zespół korzysta (i zaleca) następujące opcje kompilacji:

-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

Włącz je w swoim projekcie i dowiedz się wiele o swoim kodzie.

Trzymaj się standardu

Staraj się nie używać rzeczy zależnych od platformy, jeśli istnieją standardowe analogi, a jeśli absolutnie nie możesz się bez nich obejść, zawiń je w specjalne bloki na makra (lub coś innego) i po prostu nie pozwól, aby Twój kod został skompilowany w nieobsługiwanych warunkach.

Trzymaj się standardowej semantyki operacji

Dodawanie musi być dodawaniem, mnożenie musi być mnożeniem, wywołanie funkcji musi być wywołaniem funkcji, kopia musi być kopią, przeniesienie musi być przeniesieniem, kontener musi być iterowalny, iterator musi mieć promocję ++ i dereferencje *. I tak dalej i tak dalej.

Myślę, że pomysł jest jasny. Istnieją ustalone konwencje, które nie są wiążące, ale których oczekują wszyscy użytkownicy i czytelnicy Twojego kodu. Nie próbuj przechytrzyć innych, bo inaczej przechytrzysz samego siebie.

Napisz zgodny kod

Przede wszystkim mam na myśli bibliotekę standardową. Jest wysoce pożądane, aby interfejsy twoich klas i funkcji mogły być używane ze standardowymi i innymi bibliotekami (na przykład Boost).

Zachęcamy do zapoznania się z interfejsami STL i Boost. Z nielicznymi wyjątkami zobaczysz tam godny wzór do naśladowania.

Wykorzystaj w pełni narzędzia open source

Do tej samej analizy statycznej dostępne są co najmniej dwa otwarte bezpłatne narzędzia, które można podłączyć tylko raz do dowolnego projektu za pomocą systemu kompilacji CMake.

Więcej na ten temat przeczytacie w mojej ostatniej publikacji.

Posłowie

Na koniec chciałbym podkreślić, że nie jestem zwolennikiem niestosowania PVS ani żadnych innych analizatorów statycznych. Zachęcam jednak do zastanowienia się, jak to się stało, że analizator statyczny stale znajduje w Twoim kodzie istotne błędy.

To jest po prostu konsekwencja. Trzeba poszukać i wyeliminować przyczynę.

Źródło: www.habr.com

Dodaj komentarz