Flag per abilitare avvisi g ++ dettagliati e dettagliati


122

Spesso in C sotto gcc, inizierò con il seguente set di flag di avviso (assemblati dolorosamente da più fonti):

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

Costruirò (almeno le mie versioni di debug) con questo set di avvisi e sistemerò tutto ciò che posso (di solito tutto), quindi rimuoverò solo i flag se non sono rilevanti o non risolvibili (quasi mai il caso). A volte, aggiungo anche -Werrorse devo allontanarmi durante la compilazione.

Sto solo imparando il C ++ (sì, sono indietro di 15 anni rispetto ai tempi) e vorrei iniziare con il piede giusto.

La mia domanda è: qualcuno ha un set simile precompilato di flag di avviso completi per C ++ sotto g++? (So ​​che molti di loro saranno gli stessi.)


69
Quali bisogni gcc (dal momento che è palesemente deciso di mentire circa -Wall) è una -Wbloody_everythingbandiera :-)
paxdiablo

Puoi contrassegnare la tua domanda come stupida, ma puoi anche inserire l'ultima modifica come risposta poiché hai effettivamente risposto alla tua domanda. E allora sarei lieto di votare a favore :)
ereIl

4
OP e @paxdiablo: GCC ha costantemente rifiutato questo genere di cose, ma è disponibile in Clang tramite -Weverything. Ho letto che anche gli sviluppatori di Clang ++ sono un po 'preoccupati per gli utenti che lo accendono; apparentemente era inteso solo per uso di sviluppo interno. Questo non ha senso, tuttavia, perché l'attivazione -Weverythingè probabilmente il modo migliore per scoprire avvisi potenzialmente utili che non conoscevi prima.
Kyle Strand

1
OP e @paxdiablo C'è ora un modo per capire l'elenco completo degli avvisi per una data versione di GCC: github.com/barro/compiler-warnings
Kyle Strand

Risposte:


138

Ho esaminato e ho trovato il set minimo di include che dovrebbe ottenere il massimo livello di avviso. Ho quindi rimosso da tale elenco la serie di avvisi che ritengo non indicano effettivamente che sta accadendo qualcosa di brutto, oppure hanno troppi falsi positivi per essere utilizzati in una build reale. Ho commentato il motivo per cui ciascuno di quelli che ho escluso è stato escluso. Questa è la mia ultima serie di avvisi suggeriti:

-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

Avvisi discutibili presenti:

  • Includo -Wno-unusedperché spesso ho variabili che so che userò in seguito, ma non ho ancora la funzionalità scritta per. Rimuovere gli avvertimenti in merito mi consente di scrivere nel mio stile preferito di posticipare occasionalmente l'attuazione delle cose. È utile spegnerlo di tanto in tanto per assicurarsi che nulla scivoli attraverso le fessure.

  • -Wdisabled-optimizationsembra una forte impostazione delle preferenze dell'utente. Ho appena aggiunto questo alla mia build (solo per build ottimizzate per ovvi motivi) e non ha rivelato nulla, quindi non sembra essere un avvertimento particolarmente loquace, almeno per il modo in cui codifico. Lo includo (anche se il codice che attiva questo avviso non è necessariamente sbagliato) perché credo nel lavorare con i miei strumenti invece che contro di loro. Se gcc mi dice che non può ottimizzare il codice per il modo in cui l'ho scritto, allora dovrei cercare di riscriverlo. Sospetto che il codice che attiva questo avviso potrebbe trarre vantaggio dall'essere più modulare, a prescindere, quindi sebbene il codice non sia tecnicamente sbagliato (probabilmente), stilisticamente probabilmente lo è.

  • -Wfloat-equalavvisa per confronti di uguaglianza sicuri (in particolare, confronto con un valore non calcolato di -1). Un esempio nel mio codice in cui lo uso è che ho un vettore di float. Eseguo questo vettore e ci sono alcuni elementi che non posso ancora valutare come dovrebbero essere, quindi li ho impostati su -1.0f (poiché il mio problema utilizza solo numeri positivi, -1 è fuori dominio). Successivamente passo e aggiorno i valori -1.0f. Non si presta facilmente a un diverso metodo di funzionamento. Sospetto che la maggior parte delle persone non abbia questo problema e il confronto di un numero esatto in virgola mobile è probabilmente un errore, quindi lo includo nell'elenco predefinito.

  • -Wold-style-castha molti falsi positivi nel codice della libreria che sto utilizzando. In particolare, la famiglia di funzioni htonl utilizzate nel networking, nonché un'implementazione di crittografia Rijndael (AES) che sto utilizzando, ha cast vecchio stile di cui mi mette in guardia. Ho intenzione di sostituire entrambi, ma non sono sicuro che ci sia qualcos'altro nel mio codice di cui si lamenterà. La maggior parte degli utenti dovrebbe probabilmente averlo attivato per impostazione predefinita, però.

  • -Wsign-conversionè stata dura (e quasi non ha fatto la lista). L'attivazione nel mio codice ha generato un'enorme quantità di avvisi (100+). Quasi tutti erano innocenti. Tuttavia, sono stato attento a utilizzare interi con segno ovunque non ne fossi sicuro, anche se per il mio particolare dominio problematico, di solito otterrei un leggero aumento di efficienza usando valori senza segno a causa della grande quantità di divisione di interi che faccio. Ho sacrificato questa efficienza perché ero preoccupato di promuovere accidentalmente un intero con segno in un non firmato e quindi di dividere (che non è sicuro, a differenza di addizione, sottrazione e moltiplicazione). L'attivazione di questo avviso mi ha consentito di modificare in modo sicuro la maggior parte delle mie variabili in tipi non firmati e di aggiungere alcuni cast in altri punti. Attualmente è un po 'difficile da usare perché l'avviso non è così intelligente. Ad esempio, se lo faiunsigned short + (integral constant expression), quel risultato viene promosso implicitamente a int. Quindi avverte di un potenziale problema con il segno se si assegna quel valore a unsignedo unsigned short, anche se è sicuro. Questo è sicuramente l'avviso più facoltativo per quasi tutti gli utenti.

  • -Wsign-promo: vedi -Wsign-conversion.

  • -Wswitch-defaultsembra inutile (non vuoi sempre un caso predefinito se hai enumerato tutte le possibilità in modo esplicito). Tuttavia, l'attivazione di questo avviso può applicare qualcosa che probabilmente è una buona idea. Per i casi in cui si desidera ignorare esplicitamente tutto tranne le possibilità elencate (ma sono possibili altri numeri), quindi inseriredefault: break;per renderlo esplicito. Se enumeri esplicitamente tutte le possibilità, l'attivazione di questo avviso ti aiuterà ad assicurarti di inserire qualcosa come assert (false) per assicurarti di aver effettivamente coperto tutte le opzioni possibili. Ti consente di essere esplicito in quale sia il dominio del tuo problema e lo applica programmaticamente. Tuttavia, dovrai stare attento a mantenere assert (falso) ovunque. È meglio che non fare nulla con il caso predefinito, ma come al solito con assert, non funzionerà nelle build di rilascio. In altre parole, non puoi fare affidamento su di esso per convalidare i numeri che ottieni, ad esempio, da una connessione di rete o da un database su cui non hai il controllo assoluto. Le eccezioni o il ritorno anticipato sono il modo migliore per gestirlo (ma richiedono comunque di avere un caso predefinito!).

  • -Werrorè importante per me. Quando si compilano grandi quantità di codice in una build multi-thread con più destinazioni, è facile che un avviso passi. Trasformare gli avvisi in errori garantisce che io li noti.

Poi c'è una serie di avvisi che non sono inclusi nell'elenco precedente perché non li ho trovati utili. Questi sono gli avvisi e i miei commenti sul motivo per cui non li includo nell'elenco predefinito:

Avvisi assenti:

  • -Wabinon è necessario perché non sto combinando binari di compilatori diversi. Ho provato comunque a compilare con esso, e non si è attivato, quindi non sembra inutilmente prolisso.

  • -Waggregate-returnnon è qualcosa che considero un errore. Ad esempio, si attiva quando si utilizza un ciclo for basato su intervallo su un vettore di classi. L'ottimizzazione del valore di ritorno dovrebbe prendersi cura di eventuali effetti negativi di questo.

  • -Wconversiontrigger su questo codice: short n = 0; n += 2;la conversione implicita in int provoca un avviso quando viene quindi riconvertito nel tipo di destinazione.

  • -Weffc++include un avviso se tutti i membri di dati non sono inizializzati nell'elenco degli inizializzatori. In molti casi non lo faccio intenzionalmente, quindi il set di avvisi è troppo disordinato per essere utile. È utile attivarsi ogni tanto e cercare altri avvisi, tuttavia (come i distruttori non virtuali delle classi base). Ciò sarebbe più utile come raccolta di avvertimenti (come -Wall) invece di un singolo avvertimento da solo.

  • -Winlineè assente perché non uso la parola chiave inline per scopi di ottimizzazione, solo per definire le funzioni inline nelle intestazioni. Non mi interessa se l'ottimizzatore lo integra effettivamente. Questo avviso si lamenta anche se non può incorporare una funzione dichiarata nel corpo di una classe (come un distruttore virtuale vuoto).

  • -Winvalid-pch manca perché non uso intestazioni precompilate.

  • -Wmissing-format-attributenon viene utilizzato perché non uso estensioni gnu. Lo stesso per -Wsuggest-attributee molti altri

  • Potenzialmente notevole per la sua assenza è -Wno-long-long, di cui non ho bisogno. Compilo con -std=c++0x( -std=c++11in GCC 4.7), che include long longtipi interi. Quelli bloccati su C ++ 98 / C ++ 03 potrebbero prendere in considerazione l'aggiunta di tale esclusione dall'elenco degli avvisi.

  • -Wnormalized=nfc è già l'opzione predefinita e sembra essere la migliore.

  • -Wpaddedviene attivato occasionalmente per ottimizzare il layout delle classi, ma non viene lasciato acceso perché non tutte le classi hanno elementi sufficienti per rimuovere il riempimento alla fine. In teoria potrei ottenere alcune variabili extra per "gratis", ma non vale la pena di mantenerlo (se la dimensione della mia classe cambia, non è facile rimuovere quelle variabili precedentemente libere).

  • -Wstack-protector non viene utilizzato perché non lo uso -fstack-protector

  • -Wstrict-aliasing=3è attivato da -Walled è il più preciso, ma sembra che i livelli 1 e 2 forniscano più avvisi. In teoria un livello più basso è un avvertimento "più forte", ma è a costo di più falsi positivi. Il mio codice di prova è stato compilato in modo pulito sotto tutti e 3 i livelli.

  • -Wswitch-enumnon è un comportamento che voglio. Non voglio gestire esplicitamente ogni istruzione switch. Sarebbe utile se il linguaggio avesse un meccanismo per attivarlo su specifiche istruzioni switch (per garantire che le modifiche future all'enum siano gestite ovunque sia necessario), ma è eccessivo per un'impostazione "tutto o niente".

  • -Wunsafe-loop-optimizationsprovoca troppi avvisi spuri. Può essere utile applicarlo periodicamente e verificare manualmente i risultati. Ad esempio, ha generato questo avviso nel mio codice quando ho eseguito il ciclo su tutti gli elementi in un vettore per applicare loro un insieme di funzioni (utilizzando il ciclo for basato su intervallo). È anche un avvertimento per il costruttore di un array const di const std :: string (dove questo non è un loop nel codice utente).

  • -Wzero-as-null-pointer-constant e -Wuseless-cast sono solo avvisi di GCC-4.7, che aggiungerò quando passerò a GCC 4.7.

Ho inviato alcune segnalazioni di bug / richieste di miglioramento a gcc come risultato di alcune di queste ricerche, quindi spero di essere in grado di aggiungere alla fine più avvisi dall'elenco "non includere" all'elenco "include" . Questo elenco include tutti gli avvisi menzionati in questo thread (più penso alcuni extra). Molti degli avvertimenti non esplicitamente menzionati in questo post sono inclusi come parte di un altro avvertimento che menziono. Se qualcuno nota avvisi che sono completamente esclusi da questo post, fammelo sapere.

modifica: sembra che ne avessi perso diversi (che ora ho aggiunto). In realtà c'è una seconda pagina su http://gcc.gnu.org che è abbastanza ben nascosta. Opzioni di avviso generali e opzioni C ++ (scorri verso il basso fino alla fine per gli avvisi)


Recentemente ho inviato una richiesta di miglioramento basata sulla mia ricerca per questa risposta: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Semplificherebbe notevolmente la situazione di allerta creando livelli di allerta. Nella mia proposta, la mia serie di avvertimenti suggerita è approssimativamente -W4, con una proposta aggiuntiva per creare -Winf, che significherebbe -Weverything-and-I-really-mean-it-this-time
David Stone

Richiesta di miglioramento che comporterebbe l'aggiunta di parte di -Wpadded all'elenco consigliato: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone

Richiesta di miglioramento che comporterebbe l'aggiunta di parti di -Weffc ++ all'elenco consigliato: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone

1
@Predelnik: è più complicato di così. -Wswitch-enumavvisa se non gestisci esplicitamente ogni valore di enumerazione in uno switch e defaultnon conta come esplicito. D'altra parte, -Wswitch-defaultti avverte se il tuo switch non ha una defaultcustodia, anche se hai esplicitamente coperto tutti i valori possibili.
David Stone,

2
A proposito: usa al -isystemposto del -Ituo "vecchio codice libreria" per evitare tutti quei falsi positivi
galois

39

D'oh, tutte le mie ricerche originali hanno generato il 99% dei post su come sopprimere gli avvisi (abbastanza spaventosamente), ma mi sono imbattuto in questo commento , che ha questo adorabile set di flag (alcuni meno rilevanti):

Controllo incrociato con:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

Quindi, penso che sia un buon punto di partenza. Non sapevo che fosse uno stupido, ma almeno era profondamente sepolto. :-)


1
Forse, ma questo sembra cambiare tra le versioni, e probabilmente per il capriccio delle macchie solari e dell'RMS, quindi essere eccessivamente espliciti probabilmente non farà male. È comunque un buon punto di partenza.
Sdaz MacSkibbons

3
Da un rapido grep di c-opts.c / opts.c di 4.5.2 per 'case OPT_W', ti manca: strict overflow, undef, strict nul sentinel, normalized, multichar, implicit function declaration, deprecated, endif labels, commento s , integrato macro ridefinito, più grande, più grande di eq, abi. È pazzesco che non ci sia un'opzione della riga di comando per elencarli.
Tony Delroy

3
Penso che sia più folle che -Wallnon faccia quello che ci si aspetterebbe. Ma grazie, alcuni di questi sembrano molto utili!
Sdaz MacSkibbons

1
La disabilitazione degli avvisi ha il suo posto. Dopo tutto, sono "avvertimenti". Un'altra situazione è quando abiliti un flag che abilita più avvisi, ma vuoi essere selettivo al riguardo.
Tamás Szelei

1
Come sei in grado di utilizzare -Waggregate-return? Questo mi dà un avvertimento per ogni utilizzo dibegin/end()
Flamefire

13

Alcuni di questi sono già inclusi in -Wallo -Wextra.

Una buona configurazione di base per C è:

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

e per C ++

-ansi -pedantic -Wall -Wextra -Weffc++

(saltare -Werrorper C ++ dal momento che -Weffc++ha alcuni fastidi)


10
-L'errore può essere disabilitato per tipi specifici di avvisi, ad esempio: -Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing

2
ansi : in modalità C, è equivalente a -std=c89. In modalità C ++, è equivalente a -std=c++98. cioè, se ne stai specificando un altro std, non usareansi
Sean Breckenridge

2

Provare

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

È un inizio veloce e sporco che avrà sicuramente bisogno di un po 'di messa a punto; per prima cosa, anche se chiami il compilatore con il nome appropriato per la tua lingua (esg++ per C ++), riceverai avvertimenti che non si applicano a quella lingua (e il compilatore alzerà le mani e si rifiuterà di continuare finché non rimuovere l'avviso).

Un'altra cosa è che ho aggiunto -Werror, perché se non stai correggendo gli avvisi, perché ti interessa attivarli? Puoi anche eliminare gli avvisi dall'elenco. (Ad esempio, non lo uso quasi mai -Waggregate-returncon C ++.)

Alcuni avvisi non funzioneranno senza altre opzioni relative alle prestazioni ( -Wstack-protector).-fdiagnostics-show-optione il manuale di GCC sono tuoi amici.

A proposito, alcuni avvertimenti si escludono a vicenda; in particolare utilizzando -Wtraditionale -Wold-style-definitioninsieme a -Werror, non verrà compilato.


0

Nel mio Clion's CmakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.