Recensione indipendente di PVS-Studio (Linux, C++)

Ho visto una pubblicazione su come PVS ha finalmente imparato ad analizzare su Linux e ho deciso di provarlo nei miei progetti. Ecco cosa è venuto fuori.


Contenuto

  1. Pro
  2. Svantaggi
  3. Risultati
  4. Epifania

Pro

Supporto reattivo

Ho richiesto una chiave di prova e me l'hanno inviata lo stesso giorno.

Documentazione sufficientemente chiara

Sono riuscito a far funzionare l'analizzatore senza particolari problemi. È disponibile anche una guida per i comandi della console (sebbene ci siano alcune lamentele, vedi la sezione Svantaggi).

Possibilità di analisi multithread

L'analizzatore ha un'opzione 'standard' -j, che consente di eseguire analisi in parallelo su più attività. Questo fa risparmiare molto tempo.

Buona visualizzazione

Molti formati di output diversi, dal testo a una piccola interfaccia web. L'interfaccia web è comoda, concisa, con suggerimenti accanto alle righe di codice e collegamenti alle descrizioni delle diagnosi..

Integrazione facile nella costruzione

tutta la documentazione è disponibile sul loro sito. Volevo solo dire che se il vostro progetto viene costruito con CMake, è tutto molto semplice.

Buone descrizioni delle diagnosi

Se si genera output in modalità fullhtml, ogni messaggio ha un collegamento alla descrizione della diagnosi, con spiegazioni, esempi di codice e collegamenti aggiuntivi.

Svantaggi

Non conoscenza dell'analizzatore del linguaggio C++

Sfortunatamente, PVS a volte commette errori di sintassi e genera falsi positivi con codice del tutto valido.

Ad esempio, c'è una funzione che restituisce void:

template 
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));
}

Sì, la parola chiave auto può significare void, ed è per questo che è auto. Ma PVS ha generato i seguenti messaggi:

dynamic_tuple_management.hpp:29:1: errore: V591 La funzione non-void dovrebbe restituire un valore.
dynamic_tuple_management.hpp:29:1: errore: V2542 Funzione con un tipo di ritorno non-void dovrebbe restituire un valore da tutti i percorsi di uscita.

Sito estremamente lento

Sì, nell'interfaccia web accanto a ogni messaggio c'è un link alla descrizione diagnostica corrispondente con esempi. Ma cliccando sul link, a volte si deve aspettare a lungo, e a volte si verifica anche 504 Gateway Time-out.

Linguaggio

Tutte le descrizioni sono in russo, il che è ottimo. Ma i link nel rapporto conducono sempre alla versione in inglese. Sarebbe utile avere la possibilità di cambiare lingua, in modo da poter visualizzare la diagnostica direttamente in russo. Non ho trovato tale opzione nell'interfaccia.

È scomodo lavorare con i livelli diagnostici tramite la console

Iniziamo col dire che i due comandi utilizzati (questo pvs-studio-analyzer e plog-converter) hanno formati di diagnosi diversi.

La guida a pvs-studio-analyzer dice:

-a [MODE], --analysis-mode [MODE]
    MODE definisce il tipo di avvisi:
    1 - errori a 64 bit;
    2 - riservato;
    4 - Analisi Generale;
    8 - Micro-ottimizzazioni;
    16 - Richieste Specifiche dei Clienti;
    32 - MISRA.
    I modi possono essere combinati sommando i valori
    Default: 4

Ho cercato a lungo di capire dove dovessi aggiungere le chiavi ("adding the values"). Ho provato a elencarle con una virgola:

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

Ho provato a specificare la chiave più volte:

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

E solo dopo ho capito che erano maschere di bit! E dovevo sommare, e non aggiungere i valori. Ad esempio, per ottenere diagnosi generali, diagnosi per micro-ottimizzazioni e MISRA, dovevo sommarli (4 + 8 + 32 = 44):

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

L'uso delle maschere di bit nelle interfacce utente è, di norma, una cattiva prassi. Tutto ciò si poteva sommare internamente, e all'utente solo esporre un insieme di flag.

Inoltre, c'è anche un'utilità plog-converter, che genera informazioni leggibili dall'uomo sull'analisi statica. Ha altre peculiarità.

La guida al programma plog-converter riporta:

-a, --analyzer            Specifica l'analisi e i livelli da utilizzare per il filtraggio, cioè 'GA:1,2;64:1;OP:1,2,3;CS:1;MISRA:1,2' Default: GA:1,2

Qui sono apparsi alcuni "livelli" che prima non c'erano, e non ho trovato nulla in merito nella documentazione.

In generale, non è chiaro. Quindi ho impostato tutto al massimo.

Un sacco di lamentele inutili su Catch

In due dei tre progetti che ho analizzato, è stata utilizzata la libreria di test modulare Catch2. E la maggior parte dei messaggi (!!! 90 su 138 in uno e 297 su 344 nell'altro !!!) ha il seguente aspetto:

Recensione indipendente di PVS-Studio (Linux, C++)

Non considera il multithreading

Molti falsi positivi riguardo a presunti cambiamenti delle variabili o cicli infiniti, mentre l'operazione su quelle variabili avviene da diversi thread, e se non fosse così, i test modulari non avrebbero funzionato.

Recensione indipendente di PVS-Studio (Linux, C++)

Comunque, può un analizzatore statico considerare una cosa simile? Non lo so.

Risultati

PVS non ha trovato errori reali nei miei progetti aperti Burst e Proxima, e in un progetto lavorativo che, per ovvi motivi, non posso presentare. È giusto notare che alcune mancanze erano già state individuate e corrette in precedenza. Cppcheck e scan-build.

In generale, l'impressione di tutti questi analizzatori è più o meno la stessa: sì, catturano qualcosa, a volte anche cose importanti, ma nel complesso un compilatore è sufficiente.

Forse (e a me piace pensarlo così), la nostra squadra utilizza pratiche di sviluppo software che riducono al minimo la generazione di codice scadente. È meglio non creare problemi piuttosto che affrontarli eroicamente.

Pertanto, mi prendo la libertà di dare alcuni consigli su come scrivere in C++ in modo da non colpire nessuno e non ricevere colpi in testa dalle zappe.

Utilizzate al massimo le diagnosi del compilatore

Il nostro team utilizza (e vi consiglia) le seguenti opzioni di compilazione:

-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

Includetele nel vostro progetto, imparerete molto sul vostro codice.

Attenetevi agli standard

Cerca di non utilizzare elementi dipendenti dalla piattaforma, se ci sono analoghi standard; e se non puoi farne a meno, incapsulali in blocchi speciali per macros (o in un altro modo) e non permettere semplicemente che il tuo codice venga compilato in condizioni non supportate.

Attieniti alla semantica standard delle operazioni

L'addizione deve essere addizione, la moltiplicazione deve essere moltiplicazione, la chiamata di funzione deve essere chiamata di funzione, la copia deve copiare, lo spostamento deve spostare, il contenitore deve essere iterabile, l'iteratore deve avere un avanzamento ++ e dereferenziazione *. E così via, e così via.

Penso che il concetto sia chiaro. Ci sono convenzioni consolidate che non sono obbligatorie, ma che tutti gli utenti e lettori del tuo codice si aspettano di vedere. Non cercare di ingannare gli altri, altrimenti ingannerai te stesso.

Scrivi codice compatibile

In primo luogo, mi riferisco alla libreria standard. È molto desiderabile che le interfacce delle tue classi e funzioni possano essere utilizzate con librerie standard e altre librerie (ad esempio, Boost).

Non esitate a dare un'occhiata alle interfacce STL e Boost. Fatta eccezione per pochi casi, troverete lì un eccellente esempio da seguire.

Sfruttate al massimo gli strumenti open source

Per lo stesso tipo di analisi statica, ci sono almeno due strumenti open source gratuiti che possono integrarsi facilmente in qualsiasi progetto con sistema di build CMake.

Potete leggere di più in la mia recente pubblicazione.

Epifania

Infine, voglio sottolineare che non sconsiglio l'uso di PVS o di altri analizzatori statici. Ma vi invito a riflettere su come mai l'analizzatore statico continui a trovare errori significativi nel vostro codice.

Questo è solo una conseguenza. Bisogna cercare e risolvere la causa.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster