Analisi statica – dalla conoscenza all'integrazione

Stanco di un interminabile code review o debug, a volte ti chiedi come semplificarti la vita. E cercando un po', oppure per caso, puoi imbatterti nella magica espressione: "Analisi Statica". Vediamo di cosa si tratta e come può interagire con il tuo progetto.

Analisi statica – dalla conoscenza all'integrazione
In effetti, se stai programmando in un linguaggio moderno, anche senza rendertene conto, hai già utilizzato un analizzatore statico. Infatti, qualsiasi compilatore moderno fornisce, seppur in modo minimale, un insieme di avvisi su potenziali problemi nel codice. Ad esempio, compilando codice C++ in Visual Studio potresti vedere quanto segue:

Analisi statica – dalla conoscenza all'integrazione
In questo output vediamo che la variabile var non è stata utilizzata in nessuna parte della funzione. Quindi, in realtà, hai quasi sempre utilizzato un semplice analizzatore statico di codice. Tuttavia, a differenza degli analizzatori professionali come Coverity, Klocwork o PVS-Studio, gli avvisi forniti dal compilatore possono segnalare solo un ridotto spettro di problemi.

Se non sei sicuro di cosa sia l'analisi statica e come implementarla, leggi questo articolo, per avere una comprensione più dettagliata di questa metodologia.

A cosa serve l'analisi statica?

In poche parole: accelera e semplifica.

L'analisi statica permette di scoprire una miriade di problemi diversi nel codice: dall'uso errato delle strutture linguistiche a refusi. Ad esempio, invece di

auto x = obj.x;
auto y = obj.y;
auto z = obj.z;

hai scritto il seguente codice:

auto x = obj.x;
auto y = obj.y;
auto z = obj.x;

Come puoi vedere, nell'ultima riga è presente un errore di battitura. Ad esempio, PVS-Studio emette il seguente avviso:

V537 Considera di rivedere la correttezza dell'uso dell'elemento 'y'.

Se desideri provare a toccare questo errore manualmente, prova l'esempio pronto su Compiler Explorer: *clicca*.

E come puoi capire, non sempre è possibile prestare attenzione a sezioni di codice simili immediatamente, e questo può farti rimanere bloccato nel debug per un'intera ora, chiedendoti perché tutto funzioni in modo così strano.

Tuttavia, si tratta di un errore evidente. E se uno sviluppatore ha scritto codice non ottimale perché ha dimenticato qualche sottigliezza del linguaggio? Oppure ha addirittura introdotto nel codice comportamento indefinito? К сожалению, подобные случаи совершенно обыденны и львиная часть времени тратится на то, чтобы отладить специфично работающий код, который содержит опечатки, типичные ошибки или undefined behavior.

È proprio per queste situazioni che è nato l'analisi statica. È un assistente per lo sviluppatore che gli indica vari problemi nel codice e spiega nella documentazione perché non si dovrebbe scrivere in quel modo, a cosa può portare e come correggerlo. Ecco un esempio di come potrebbe apparire:clicca*.

Puoi trovare più errori interessanti che l'analizzatore può rilevare negli articoli:

Ora che hai letto questo materiale e ti sei reso conto dell'utilità dell'analisi statica, potresti volerla mettere alla prova. Ma da dove iniziare? Come integrare il nuovo strumento nel progetto attuale? E come presentarlo al team? Troverai le risposte a queste domande qui sotto.

Nota. L'analisi statica non sostituisce e non annulla una cosa utile come le revisioni del codice. Essa integra questo processo, aiutando a notare e correggere in anticipo errori di battitura, imprecisioni e costrutti pericolosi. È molto più produttivo concentrarsi sulle algoritmi e sulla chiarezza del codice durante le revisioni, piuttosto che cercare parentesi inserite in modo errato o leggere noiose funzioni di confronto.

0. Introduzione allo strumento

Tutto inizia con una versione di prova. Infatti, è difficile decidere di implementare qualcosa nel processo di sviluppo se non si è mai visto uno strumento dal vivo. Pertanto, la prima cosa da fare è scaricare la versione di prova.

Cosa imparerai in questo passaggio:

  • Quali sono i modi per interagire con l'analizzatore;
  • Se l'analizzatore è compatibile con il tuo ambiente di sviluppo;
  • Quali problemi ci sono attualmente nei tuoi progetti.

Dopo aver installato tutto il necessario, la prima cosa da fare è avviare l'analisi dell'intero progetto (Windows, Linux, macOS). Nel caso di PVS-Studio in Visual Studio vedrai un'immagine simile (cliccabile):

Analisi statica – dalla conoscenza all'integrazione
Il fatto è che di solito gli analizzatori statici forniscono un'enorme quantità di avvisi per progetti con una grande base di codice. Non è necessario correggerli tutti, poiché il tuo progetto è già funzionante e quindi questi problemi non sono critici. Tuttavia, puoi dare un'occhiata agli avvisi più interessanti e correggerli se necessario. Per questo è necessario filtrare l'output e mantenere solo i messaggi più affidabili. Nel plugin PVS-Studio per Visual Studio questo si fa filtrando per livelli e categorie di errori. Per un output più preciso, lasciate attivi solo High e Generale (anch'esso cliccabile):

Analisi statica – dalla conoscenza all'integrazione
Infatti, esaminare 178 avvisi è decisamente più semplice che affrontare diverse migliaia…

Nelle schede Medium e Basso spesso si trovano avvisi utili, tuttavia in queste categorie sono incluse quelle diagnosi che hanno una minore precisione (affidabilità). Per maggiori dettagli sui livelli di avvisi e le varianti di lavoro su Windows, è possibile controllare qui: *clicca*.

Dopo aver esaminato gli errori più interessanti (e averli corretti), è opportuno sopprimere gli avvisi rimanenti. Questo è necessario affinché i nuovi avvisi non si perdano tra i vecchi. Inoltre, l'analizzatore statico è un aiuto per il programmatore, non un elenco di bug. 🙂

1. Automazione

Dopo la familiarizzazione, arriva il momento di configurare i plugin e integrarli nel CI. È necessario farlo prima che i programmatori inizino a usare l'analizzatore statico. Il fatto è che un programmatore potrebbe dimenticare di attivare l'analisi o semplicemente non volerlo fare. È importante effettuare una certa verifica finale affinché il codice non verificato non possa entrare nel ramo di sviluppo generale.

Cosa scoprirete in questa fase:

  • Quali opzioni di automazione offre lo strumento;
  • Se l'analizzatore è compatibile con il vostro sistema di build.

Poiché non esiste documentazione ideale, a volte è necessario scrivere a supporto. È normale, e siamo lieti di aiutarvi. 🙂

Ora passiamo ai servizi di integrazione continua (CI). Qualsiasi analizzatore può essere implementato senza particolari problemi. È necessario creare una fase separata nel pipeline, che di solito si trova dopo la compilazione e i test unitari. Questo si fa utilizzando varie utility da console. Ad esempio, PVS-Studio fornisce le seguenti utility:

Per integrare l'analisi nel CI è necessario fare tre cose:

  • Installare l'analizzatore;
  • Eseguire l'analisi;
  • Consegnare i risultati.

Ad esempio, per installare PVS-Studio su Linux (basato su Debian) è necessario eseguire i seguenti comandi:

wget -q -O - https://files.viva64.com/etc/pubkey.txt 
    | sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list 
  https://files.viva64.com/etc/viva64.list
  
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio

Nei sistemi operativi Windows non è possibile installare l'analizzatore tramite il gestore di pacchetti, ma c'è la possibilità di distribuire l'analizzatore dalla linea di comando:

PVS-Studio_setup.exe /verysilent /suppressmsgboxes 
/norestart /nocloseapplications

Ulteriori dettagli sulla distribuzione di PVS-Studio sui sistemi Windows possono essere letti *qui*.

Dopo l'installazione, è necessario avviare direttamente l'analisi. Tuttavia, si consiglia di farlo solo dopo che la compilazione e i test sono stati completati. Questo perché per l'analisi statica è generalmente necessario un tempo doppio rispetto alla compilazione.

Poiché il modo di avvio dipende dalla piattaforma e dalle caratteristiche del progetto, mostrerò un'opzione per C++ (Linux) come esempio:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log
plog-converter -t errorfile PVS-Studio.log --cerr -w

Il primo comando eseguirà l'analisi, mentre il secondo converteil rapporto in formato testo, lo visualizzerà a schermo e restituirà un codice di ritorno diverso da 0 in caso di avvisi. Un meccanismo di questo tipo è utile per bloccare la compilazione quando sono presenti messaggi di errore. Tuttavia, è sempre possibile rimuovere il flag -w e non bloccare la compilazione che contiene avvisi.

Nota. Il formato testo non è pratico. Viene fornito solo come esempio. Prendi nota di un formato di report più interessante — FullHtml. Esso consente di navigare nel codice.

Ulteriori informazioni sulla configurazione dell'analisi su CI possono essere lette nell'articolo "PVS-Studio e Continuous Integration" (Windows) oppure "Come configurare PVS-Studio in Travis CI" (Linux).

Bene, hai configurato il lavoro dell'analizzatore sul server di build. Ora, se qualcuno ha caricato codice non verificato, fallirà la fase di verifica e potrai individuare il problema; tuttavia, questo non è molto conveniente, poiché è più efficace controllare il progetto non dopo che è avvenuta la fusione dei rami, ma prima, nella fase della richiesta di pull.

In generale, la configurazione dell'analisi della richiesta di pull non differisce molto dall'esecuzione dell'analisi normale su CI. Tranne per la necessità di ottenere l'elenco dei file modificati. Di solito, possono essere ottenuti richiedendo la differenza tra i rami tramite git:

git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list

Ora è necessario passare all'analizzatore l'elenco di file. Ad esempio, in PVS-Studio questo è implementato tramite un flag -S:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log 
                            -S .pvs-pr.list

Puoi scoprire di più sull'analisi delle pull request *qui*. Anche se il tuo CI non è nella lista dei servizi indicati nell'articolo, ti sarà utile la sezione generale dedicata alla teoria di questo tipo di analisi.

Configurando l'analisi delle pull request potrai bloccare i commit che contengono avvisi, creando così un confine che il codice non verificato non potrà oltrepassare.

Tutto ciò è indubbiamente buono, ma sarebbe utile avere la possibilità di visualizzare tutti gli avvisi in un unico posto. Non solo da parte dell'analizzatore statico, ma anche dai test unitari o dall'analizzatore dinamico. A questo scopo esistono vari servizi e plugin. PVS-Studio, ad esempio, ha un plugin per l'integrazione in SonarQube.

2. Integrazione sulle macchine degli sviluppatori

Ora è giunto il momento di installare e configurare l'analizzatore per un uso quotidiano nello sviluppo. A questo punto hai già familiarizzato con la maggior parte dei metodi di lavoro, quindi questa può essere considerata la parte più semplice.

Come opzione più semplice, gli sviluppatori possono installare autonomamente l'analizzatore necessario. Tuttavia, questo richiederà molto tempo e li distoglierà dalla programmazione, quindi puoi automatizzare questo processo utilizzando un installer e le opportune flag. Per PVS-Studio ci sono vari flag per l'installazione automatizzata. D'altra parte, ci sono sempre gestori di pacchetti, ad esempio, Chocolatey (Windows), Homebrew (macOS) o decine di opzioni per Linux.

Dopo, sarà necessario installare i plugin necessari, ad esempio, per Visual Studio, IDEA, Rider ecc.

3. Uso quotidiano

A questo punto è tempo di dire qualche parola sui modi per accelerare il lavoro dell'analizzatore durante l'uso quotidiano. Un'analisi completa dell'intero progetto richiede molto tempo, ma quanto spesso cambiamo il codice tutto in una volta? È difficile che esista un refactoring così ampio da coinvolgere immediatamente l'intero codice sorgente. Il numero di file modificati alla volta raramente supera la decina, quindi ha senso analizzarli. Per tale situazione esiste la modalità di analisi incrementale. Solo non spaventatevi, non è un altro strumento. È una modalità speciale che consente di analizzare solo i file modificati e le loro dipendenze, e questo avviene automaticamente dopo la compilazione, se state lavorando in un IDE con il plugin installato.

Nel caso in cui l'analizzatore rilevi problemi nel codice recentemente modificato, ne informerà autonomamente. Ad esempio, PVS-Studio vi avviserà tramite una notifica:

Analisi statica – dalla conoscenza all'integrazione
Naturalmente, non è sufficiente dire agli sviluppatori di utilizzare lo strumento. È necessario spiegare loro di cosa si tratta e come funziona. Ecco, ad esempio, articoli su come iniziare rapidamente con PVS-Studio, tuttavia, tutorial simili li potrete trovare per qualsiasi strumento preferito:

Articoli come questi forniscono tutte le informazioni necessarie per un utilizzo quotidiano e non richiedono molto tempo. 🙂

Già nella fase di introduzione allo strumento, abbiamo disabilitato un gran numero di avvisi durante uno dei primi avvii. Purtroppo, gli analizzatori statici non sono perfetti, quindi di tanto in tanto producono falsi positivi. È solitamente facile disabilitarli, ad esempio, nel plugin PVS-Studio per Visual Studio basta premere un pulsante:

Analisi statica – dalla conoscenza all'integrazione
Tuttavia, non potete solo disabilitarli. Ad esempio, potete segnalare il problema al supporto. Se un falso positivo può essere corretto, nei futuri aggiornamenti potrete notare che il numero di falsi positivi specifici per il vostro codice diminuisce sempre di più.

Dopo l'integrazione

Eccoci giunti a tutti i passaggi per integrare l'analisi statica nel processo di sviluppo. Nonostante l'importanza della configurazione di tali strumenti nel CI, il luogo principale di esecuzione è proprio il computer dello sviluppatore. Infatti, l'analizzatore statico non è un giudice che dice da lontano che il codice non vale nulla. Al contrario, è un assistente che suggerisce se siete stanchi e ricorda se avete dimenticato qualcosa.

La verità è che, senza un uso regolare, l'analisi statica difficilmente semplificherà notevolmente lo sviluppo. Infatti, il suo principale vantaggio per gli sviluppatori non è tanto nella ricerca di aree di codice complesse e controverse, quanto nella loro rilevazione precoce. Concordate che scoprire un problema quando le modifiche sono passate in fase di test non è solo spiacevole, ma anche molto lungo. L'analisi statica, tuttavia, se utilizzata regolarmente, esamina ogni modifica direttamente sul vostro computer e segnala luoghi sospetti mentre si lavora sul codice.

E se voi o i vostri colleghi non siete ancora sicuri se implementare l'analizzatore, vi propongo di passare ora alla lettura dell'articolo "Motivi per cui implementare l'analizzatore statico di codice PVS-Studio nel processo di sviluppo". In esso sono state analizzate le preoccupazioni tipiche degli sviluppatori riguardo al fatto che l'analisi statica ruberà loro tempo e così via.

Analisi statica – dalla conoscenza all'integrazione

Se desideri condividere questo articolo con un pubblico anglofono, ti prego di utilizzare il link alla traduzione: Maxim Zvyagintsev. Analisi Statica: Dal Prendere Avvio all'Integrazione.

Fonte: habr.com

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