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
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 ).
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. .
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.
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 .
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: 4Ho 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,16Ho provato a specificare la chiave più volte:
pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16E 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 44L'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,2Qui 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 . E la maggior parte dei messaggi (!!! 90 su 138 in uno e 297 su 344 nell'altro !!!) ha il seguente aspetto:

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.

Comunque, può un analizzatore statico considerare una cosa simile? Non lo so.
PVS non ha trovato errori reali nei miei progetti aperti e , 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. e .
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-promoIncludetele 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.
.
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
