Warning Peaks – perchè i warning sono importanti in C (e C++) – pt.1

W

Warning Peaks
perché i warning sono importanti in C (e C++) – pt.1

Dale Cooper: [parlando a un registratore] Diane, quando due eventi, due fatti riguardanti la stessa indagine si verificano simultaneamente, dobbiamo sempre considerarli con la massima attenzione.

Nella bellissima (e mitica) serie TV Twin Peaks il Maestro David Lynch (insieme al fido Mark Frost) ci spiegava che nulla è come appare a prima vista, e che in una investigazione bisogna analizzare tutti i dettagli, anche i più insignificanti, per giungere alla verità. Ebbene si, questo è valido anche nella nostra amata programmazione in C: il nostro strumento principale è il compilatore, che oltre a costruire l’eseguibile dell’applicazione su cui abbiamo lavorato ci fornisce un sacco di informazioni utili sul codice che abbiamo scritto, mostrandoci errori, vulnerabilità e avvisi, i famosi warning, che sono molto (ma molto) più importanti di quello che si pensa… Come avrete già intuito, in questo articolo parleremo di warning!

warning-peaks
…ma l’hai letto l’ultimo warning?…

Nella mia lunga carriera di programmatore ho incontrato, a volte, colleghi che non davano la dovuta attenzione ai warning di compilazione, considerandoli semplici avvisi di scarsa importanza… e questo è un errore fondamentale! Anzi, ora che ci penso, un giorno assistei a un interessante dialogo tra mio cuggino e un suo collega. Si, credo che sia ora di far intervenire (sia pur indirettamente) mio cuggino, che manca da tempo da queste pagine. Il dialogo che intercettai era, più o meno, questo:

mio cuggino: Tu sei un programmatore professionista, vero?
programmatore: Si, è il mio mestiere. Anni e anni di esperienza...
mio cuggino: Ma dimmi una cosa: quando compili che linea di compilazione usi?
programmatore: Mah, qualcosa del tipo "gcc -o programma programma.c".
mio cuggino: Ma lo sai che con quella linea vedi solo i warning di base? E così te ne sfuggono alcuni molto importanti.
programmatore: Beh, ma i warning sono solo avvertenze, non servono a niente, già vedere quelli di base mi confonde abbastanza le idee...
mio cuggino: Guarda, se vuoi sviluppare del buon codice dovresti perlomeno attivare il flag -Wall e magari anche il -Wextra...
programmatore: -Wall? -Wextra? Mai sentiti, a cosa servono?. 
mio cuggino: Mai pensato di cambiare mestiere?

Ecco, come sempre mio cuggino fu molto tranciante, ma quella volta io pensai la stessa cosa, ma non lo dissi (tanto l’aveva già detto lui, ah ah ah… si scherza, eh!).

Come dite? Sto esagerando? Ok, allora è il caso di fornire qualche piccolo esempietto… vai col codice!

// uninit.c
#include <stdio.h>

int main() 
{
    int index;
    char *str = "salve, mondo";

    printf("%c\n", str[index]);
    return 0;
}

Ecco, questo è un codice semplicissimo che stampa il contenuto di una stringa. Proviamo a compilare ed eseguire questo uninit.c:

aldo@Linux $ gcc uninit.c -o uninit
aldo@Linux $ ./uninit 
Errore di segmentazione (core dump creato)

Ma va! Un bel segmentation fault per un codice così semplice! E il compilatore non mi dice nulla? Proviamo a aggiunger il flag -Wall:

aldo@Linux $ gcc -Wall uninit.c -o uninit
uninit.c: In function ‘main’:
uninit.c:9:23: warning: ‘index’ is used uninitialized [-Wuninitialized]
    9 |     printf("%c\n", str[index]);
      |                       ^
uninit.c:6:9: note: ‘index’ was declared here
    6 |     int index;
      |         ^~~~~

Oohh… e io che pensavo che i warning non servissero a niente (ah ah ah). Ecco, il codice mostrato è un semplice main di cinque righe, e quindi l’errore si vede facilmente, ma immaginate quando questo pezzetto di codice viene immerso in un grande progetto di centinaia di migliaia di linee: diventerà quasi invisibile, e per risolvere il problema sarà meglio dare un occhiata ai warning, no?

Ed ora un altro esempio con un warning che prima usciva solo attivando il flag -Wformat (che è incluso nel -Wall) e che ora esce anche a livello base (senza nessun flag), ma che molti non notano “perché leggere tutti i warning non serve” (ehm…) :

// format.c
#include <stdio.h>

int main() 
{
    int a = 12;
    
    printf("%s\n", a);
    return 0;
}

Ok, anche questo è un codice semplicissimo che stampa nel terminale una stringa. Proviamo a compilare ed eseguire questo format.c:

aldo@Linux $ gcc format.c -o format
format.c: In function ‘main’:
format.c:8:14: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
    8 |     printf("%s\n", a);
      |             ~^     ~
      |              |     |
      |              |     int
      |              char *
      |             %d
aldo@Linux $ ./format 
Errore di segmentazione (core dump creato)

Ma va! Un altro bel segmentation fault per un codice così semplice! E il compilatore me lo dice già di base! Certo che se non dò peso al warning (magari perché ce ne sono così tanti che faccio finta di non vederli…) il problema verrà poi quando eseguo l’applicazione. Male, male, molto male…

E non parliamo dei problemi che non appaiono costantemente a run-time, perché dipendono, sfortunatamente, da come è occupata la memoria al momento dell’esecuzione (quindi, a volte appaiono e a volte no): costerà moltissimo risolvere questi errori, quando invece sarebbe stato sufficiente risolvere tutti i warning di compilazione man mano che si presentavano! Spero di essere stato chiaro: i warning sono importanti, e non solo quelli di base!

Ok, per oggi può bastare. Nella seconda parte dell’articolo vedremo una panoramica dei flag di compilazione consigliati per realizzare una applicazione a prova di bomba. Come sempre vi raccomando di non trattenere il respiro nell’attesa (può nuocere gravemente alla salute…).

Ciao, e al prossimo post!

A proposito di me

Aldo Abate

È un Cinefilo prestato alla Programmazione in C. Per mancanza di tempo ha rinunciato ad aprire un CineBlog (che richiede una attenzione quasi quotidiana), quindi ha deciso di dedicarsi a quello che gli riesce meglio con il poco tempo a disposizione: scrivere articoli sul suo amato C infarcendoli di citazioni Cinematografiche. Il risultato finale è ambiguo e spiazzante, ma lui conta sul fatto che il (si spera) buon contenuto tecnico induca gli appassionati di C a leggere ugualmente gli articoli ignorando la parte Cinefila.
Ma in realtà il suo obiettivo principale è che almeno un lettore su cento scopra il Cinema grazie al C...

Di Aldo Abate

Gli articoli più letti

Articoli recenti

Commenti recenti