Flags, um gründliche und ausführliche g ++ - Warnungen zu aktivieren


122

Oft gccbeginne ich in C unter mit den folgenden Warnflags (schmerzhaft aus mehreren Quellen zusammengestellt):

-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

Ich werde (zumindest meine Debug-Versionen) mit diesen Warnungen erstellen und alles reparieren, was ich kann (normalerweise alles), und dann nur Flags entfernen, wenn sie entweder nicht relevant oder nicht reparierbar sind (fast nie der Fall). Manchmal füge ich auch hinzu, -Werrorwenn ich beim Kompilieren zurücktreten muss.

Ich lerne gerade C ++ (ja, ich bin 15 Jahre hinter der Zeit zurück) und möchte auf dem richtigen Fuß beginnen.

Meine Frage ist: Hat jemand einen vorkompilierten ähnlichen Satz vollständiger Warnflags für C ++ unter g++? (Ich weiß, dass viele von ihnen gleich sein werden.)


69
Was gcc Bedürfnisse (da es offensichtlich entschieden ist Lüge über -Wall) ist ein -Wbloody_everythingFlag :-)
paxdiablo

Sie können Ihre Frage als Betrug markieren, aber Sie können auch Ihre letzte Änderung als Antwort angeben, da Sie Ihre Frage tatsächlich beantwortet haben. Und ich würde mich freuen , es upvote dann :)
Ereon

4
OP und @paxdiablo: GCC hat solche Dinge konsequent abgelehnt , ist aber in Clang via verfügbar -Weverything. Ich habe gelesen, dass selbst die Clang ++ - Entwickler ein wenig besorgt darüber sind, dass Benutzer es einschalten. anscheinend war es nur für den internen entwicklungsgebrauch gedacht. Das macht keinen Sinn, wenn auch, weil das Einschalten -Weverythingist wahrscheinlich die beste Art und Weise möglicherweise hilfreich Warnungen zu entdecken , dass Sie nicht kennen , bevor.
Kyle Strand

1
OP und @paxdiablo Es gibt jetzt eine Möglichkeit, die vollständige Liste der Warnungen für eine bestimmte GCC-Version herauszufinden: github.com/barro/compiler-warnings
Kyle Strand

Antworten:


137

Ich ging durch und fand die minimale Anzahl von Includes, die die maximale Warnstufe erhalten sollten. Ich habe dann die Warnungen aus dieser Liste entfernt, die meiner Meinung nach nicht darauf hinweisen, dass etwas Schlimmes passiert, oder zu viele Fehlalarme haben, um in einem echten Build verwendet zu werden. Ich kommentierte, warum alle von mir ausgeschlossenen ausgeschlossen wurden. Dies ist meine letzte Reihe von vorgeschlagenen Warnungen:

-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

Fragwürdige Warnungen, die vorhanden sind:

  • Ich füge hinzu, -Wno-unusedweil ich oft Variablen habe, von denen ich weiß, dass ich sie später verwenden werde, aber noch nicht die Funktionalität habe, für die ich geschrieben habe. Durch das Entfernen von Warnungen kann ich in meinem bevorzugten Stil schreiben und gelegentlich die Implementierung von Dingen verschieben. Es ist nützlich, dies von Zeit zu Zeit auszuschalten, um sicherzustellen, dass nichts durch die Risse rutscht.

  • -Wdisabled-optimizationscheint eine starke Benutzereinstellung zu sein. Ich habe dieses gerade zu meinem Build hinzugefügt (nur für optimierte Builds aus offensichtlichen Gründen) und es hat nichts ergeben, daher scheint es keine besonders gesprächige Warnung zu sein, zumindest für die Art und Weise, wie ich codiere. Ich füge es hinzu (obwohl Code, der diese Warnung auslöst, nicht unbedingt falsch ist), weil ich daran glaube, mit meinen Tools zu arbeiten, anstatt gegen sie. Wenn gcc mir sagt, dass es den Code nicht für die Art und Weise optimieren kann, wie ich ihn geschrieben habe, sollte ich versuchen, ihn neu zu schreiben. Ich vermute, dass Code, der diese Warnung auslöst, davon profitieren könnte, unabhängig davon modularer zu sein. Obwohl der Code (wahrscheinlich) technisch nicht falsch ist, ist er es stilistisch wahrscheinlich.

  • -Wfloat-equalwarnt vor sicheren Gleichheitsvergleichen (insbesondere Vergleich mit einem nicht berechneten Wert von -1). Ein Beispiel in meinem Code, in dem ich dies verwende, ist, dass ich einen Float-Vektor habe. Ich gehe diesen Vektor durch und es gibt einige Elemente, die ich noch nicht bewerten kann, was sie sein sollten. Deshalb setze ich sie auf -1,0f (da mein Problem nur positive Zahlen verwendet, liegt -1 außerhalb der Domäne). Ich gehe später durch und aktualisiere -1.0f Werte. Es eignet sich nicht leicht für eine andere Arbeitsweise. Ich vermute, dass die meisten Leute dieses Problem nicht haben, und der Vergleich einer exakten Zahl im Gleitkomma ist wahrscheinlich ein Fehler, deshalb nehme ich ihn in die Standardliste auf.

  • -Wold-style-castDer von mir verwendete Bibliothekscode enthält viele Fehlalarme. Insbesondere die im Netzwerk verwendete htonl-Funktionsfamilie sowie eine von mir verwendete Rijndael (AES) -Verschlüsselungsimplementierung weisen Casts im alten Stil auf, vor denen ich gewarnt werde. Ich beabsichtige, beide zu ersetzen, bin mir aber nicht sicher, ob mein Code noch etwas enthält, über das er sich beschweren wird. Die meisten Benutzer sollten dies jedoch wahrscheinlich standardmäßig aktiviert haben.

  • -Wsign-conversionwar eine schwierige Frage (und hätte es fast nicht auf die Liste geschafft). Das Aktivieren in meinem Code erzeugte eine große Anzahl von Warnungen (100+). Fast alle von ihnen waren unschuldig. Ich habe jedoch darauf geachtet, vorzeichenbehaftete Ganzzahlen zu verwenden, wo immer ich nicht sicher war, obwohl ich für meine spezielle Problemdomäne aufgrund der großen Anzahl von Ganzzahldivisionen, die ich mache, normalerweise eine leichte Effizienzsteigerung mit vorzeichenlosen Werten erzielen würde. Ich habe diese Effizienz geopfert, weil ich besorgt war, versehentlich eine vorzeichenbehaftete Ganzzahl in eine vorzeichenlose Ganzzahl umzuwandeln und dann zu teilen (was im Gegensatz zu Addition, Subtraktion und Multiplikation nicht sicher ist). Durch Aktivieren dieser Warnung konnte ich die meisten meiner Variablen sicher in vorzeichenlose Typen ändern und an einigen anderen Stellen einige Casts hinzufügen. Es ist derzeit etwas schwierig zu verwenden, da die Warnung nicht so intelligent ist. Zum Beispiel, wenn Sie dies tununsigned short + (integral constant expression)wird dieses Ergebnis implizit zu int befördert. Es warnt dann vor einem möglichen Vorzeichenproblem, wenn Sie diesen Wert unsignedoder zuweisen, unsigned shortobwohl er sicher ist. Dies ist definitiv die optionalste Warnung für fast alle Benutzer.

  • -Wsign-promo: sehen -Wsign-conversion.

  • -Wswitch-defaultscheint sinnlos (Sie möchten nicht immer einen Standardfall, wenn Sie alle Möglichkeiten explizit aufgezählt haben). Das Aktivieren dieser Warnung kann jedoch etwas erzwingen, das wahrscheinlich eine gute Idee ist. In Fällen, in denen Sie explizit alles außer den aufgeführten Möglichkeiten ignorieren möchten (aber andere Zahlen sind möglich), geben Sie eindefault: break;um es explizit zu machen. Wenn Sie alle Möglichkeiten explizit auflisten, können Sie durch Aktivieren dieser Warnung sicherstellen, dass Sie so etwas wie assert (false) eingeben, um sicherzustellen, dass Sie tatsächlich alle möglichen Optionen abgedeckt haben. Sie können damit explizit angeben, in welcher Domäne sich Ihr Problem befindet, und dies programmgesteuert durchsetzen. Sie müssen jedoch vorsichtig sein, wenn Sie die Behauptung (falsch) überall festhalten. Es ist besser, als mit dem Standardfall nichts zu tun, aber wie bei Assert üblich, funktioniert es in Release-Builds nicht. Mit anderen Worten, Sie können sich nicht darauf verlassen, dass Sie Nummern validieren, die Sie beispielsweise von einer Netzwerkverbindung oder einer Datenbank erhalten, über die Sie keine absolute Kontrolle haben. Ausnahmen oder frühzeitige Rückkehr sind der beste Weg, um damit umzugehen (aber Sie müssen immer noch einen Standardfall haben!).

  • -Werrorist wichtig für mich. Wenn Sie große Codemengen in einem Multithread-Build mit mehreren Zielen kompilieren, kann eine Warnung leicht übersehen werden. Das Verwandeln von Warnungen in Fehler stellt sicher, dass ich sie bemerke.

Dann gibt es eine Reihe von Warnungen, die nicht in der obigen Liste enthalten sind, weil ich sie nicht als nützlich empfunden habe. Dies sind die Warnungen und meine Kommentare dazu, warum ich sie nicht in die Standardliste aufnehme:

Warnungen fehlen:

  • -Wabiwird nicht benötigt, da ich keine Binärdateien von verschiedenen Compilern kombiniere. Ich habe trotzdem versucht, damit zu kompilieren, und es hat nicht ausgelöst, so dass es nicht unnötig ausführlich erscheint.

  • -Waggregate-returnist nicht etwas, das ich als Fehler betrachte. Beispielsweise wird es ausgelöst, wenn eine bereichsbasierte for-Schleife für einen Klassenvektor verwendet wird. Die Rückgabewertoptimierung sollte negative Auswirkungen berücksichtigen.

  • -WconversionAuslöser für diesen Code: short n = 0; n += 2;Die implizite Konvertierung in int verursacht eine Warnung, wenn sie dann wieder in ihren Zieltyp konvertiert wird.

  • -Weffc++enthält eine Warnung, wenn nicht alle Datenelemente in der Initialisierungsliste initialisiert sind. Ich mache dies in vielen Fällen absichtlich nicht, daher sind die Warnungen zu überladen, um nützlich zu sein. Es ist jedoch hilfreich, ab und zu einzuschalten und nach anderen Warnungen zu suchen (z. B. nicht virtuelle Destruktoren von Basisklassen). Dies wäre nützlicher als eine Sammlung von Warnungen (wie -Wall) anstelle einer einzelnen Warnung für sich.

  • -Winlinefehlt, weil ich das Inline-Schlüsselwort nicht zu Optimierungszwecken verwende, nur um Funktionen in Headern inline zu definieren. Es ist mir egal, ob der Optimierer es tatsächlich inline. Diese Warnung beschwert sich auch, wenn eine in einem Klassenkörper deklarierte Funktion (z. B. ein leerer virtueller Destruktor) nicht integriert werden kann.

  • -Winvalid-pch fehlt, weil ich keine vorkompilierten Header verwende.

  • -Wmissing-format-attributewird nicht verwendet, da ich keine Gnu-Erweiterungen verwende. Gleiches für -Wsuggest-attributeund mehrere andere

  • Möglicherweise bemerkenswert für seine Abwesenheit ist -Wno-long-long, was ich nicht brauche. Ich kompiliere mit -std=c++0x( -std=c++11in GCC 4.7), das long longganzzahlige Typen enthält. Diejenigen, die auf C ++ 98 / C ++ 03 zurückbleiben, können diesen Ausschluss aus der Warnliste hinzufügen.

  • -Wnormalized=nfc ist bereits die Standardoption und scheint die beste zu sein.

  • -Wpaddedwird gelegentlich aktiviert, um das Layout von Klassen zu optimieren, wird jedoch nicht aktiviert, da nicht alle Klassen über genügend Elemente verfügen, um das Auffüllen am Ende zu entfernen. Theoretisch könnte ich einige zusätzliche Variablen kostenlos erhalten, aber es lohnt sich nicht, diese beizubehalten (wenn sich meine Klassengröße ändert, ist es nicht einfach, diese zuvor freien Variablen zu entfernen).

  • -Wstack-protector wird nicht verwendet, weil ich nicht benutze -fstack-protector

  • -Wstrict-aliasing=3wird von eingeschaltet -Wallund ist am genauesten, aber es sieht so aus, als würden Level 1 und 2 mehr Warnungen geben. Theoretisch ist eine niedrigere Stufe eine "stärkere" Warnung, geht jedoch zu Lasten von mehr Fehlalarmen. Mein eigener Testcode wurde unter allen 3 Ebenen sauber kompiliert.

  • -Wswitch-enumist kein Verhalten, das ich will. Ich möchte nicht jede switch-Anweisung explizit behandeln. Es wäre nützlich, wenn die Sprache einen Mechanismus hätte, um dies für bestimmte switch-Anweisungen zu aktivieren (um sicherzustellen, dass zukünftige Änderungen an der Aufzählung überall dort behandelt werden, wo sie benötigt werden), aber es ist übertrieben für eine "Alles-oder-Nichts" -Einstellung.

  • -Wunsafe-loop-optimizationsverursacht zu viele falsche Warnungen. Es kann nützlich sein, diese regelmäßig anzuwenden und die Ergebnisse manuell zu überprüfen. Als Beispiel wurde diese Warnung in meinem Code generiert, als ich alle Elemente in einem Vektor durchlaufen habe, um eine Reihe von Funktionen auf sie anzuwenden (unter Verwendung der bereichsbasierten for-Schleife). Es ist auch eine Warnung für den Konstruktor eines const-Arrays von const std :: string (wobei dies keine Schleife im Benutzercode ist).

  • -Wzero-as-null-pointer-constantund -Wuseless-castsind nur GCC-4.7-Warnungen, die ich beim Übergang zu GCC 4.7 hinzufügen werde.

Ich habe aufgrund einiger dieser Untersuchungen einige Fehlerberichte / Erweiterungsanfragen bei gcc eingereicht, sodass ich hoffentlich in der Lage sein werde, eventuell weitere Warnungen aus der Liste "Nicht einschließen" in die Liste "Einschließen" aufzunehmen . Diese Liste enthält alle in diesem Thread erwähnten Warnungen (und ich denke ein paar zusätzliche). Viele der Warnungen, die in diesem Beitrag nicht ausdrücklich erwähnt werden, sind Teil einer anderen Warnung, die ich erwähne. Wenn jemand Warnungen bemerkt, die von diesem Beitrag vollständig ausgeschlossen sind, lass es mich wissen.

edit: Es sieht so aus, als hätte ich mehrere verpasst (die ich jetzt hinzugefügt habe). Es gibt tatsächlich eine zweite Seite unter http://gcc.gnu.org , die ziemlich gut versteckt ist. Allgemeine Warnoptionen und C ++ - Optionen (für Warnungen nach unten scrollen)


Ich habe kürzlich eine Verbesserungsanfrage basierend auf meinen Recherchen für diese Antwort eingereicht : gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Dies würde die Warnsituation erheblich vereinfachen, indem Warnstufen erstellt werden. In meinem Vorschlag ist mein vorgeschlagener Satz von Warnungen ungefähr -W4, mit einem zusätzlichen Vorschlag zum Erstellen von -Winf, was bedeuten würde - Alles und ich meine es diesmal wirklich
David Stone

Eine Erweiterungsanforderung, die einen Teil von -Wpadded verursachen würde, wird der empfohlenen Liste hinzugefügt: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone

Erweiterungsanforderung, die dazu führen würde, dass Teile von -Weffc ++ zur empfohlenen Liste hinzugefügt werden: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone

1
@Predelnik: Es ist schwieriger als das. -Wswitch-enumwarnt, wenn Sie nicht jeden Aufzählungswert in einem Switch explizit behandeln und defaultnicht als explizit gelten. -Wswitch-defaultWarnt Sie andererseits, wenn Ihr Switch keinen defaultFall hat, auch wenn Sie alle möglichen Werte explizit abgedeckt haben.
David Stone

2
Übrigens - verwenden Sie -isystemanstelle -IIhres "alten Bibliothekscodes", um all diese Fehlalarme zu verhindern
Galois

39

D'oh, alle meine ursprünglichen Suchanfragen ergaben 99% der Beiträge zum Unterdrücken von Warnungen (beängstigend genug), aber ich bin gerade auf diesen Kommentar gestoßen , der diese schönen Flaggen enthält (einige weniger relevant):

Gegenübergestellt mit:

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

Ich denke, das ist ein guter Ausgangspunkt. Ich wusste nicht, dass dies ein Betrug war, aber zumindest war es tief begraben. :-)


1
Vielleicht, aber das scheint sich zwischen den Versionen zu ändern, und wahrscheinlich nach Lust und Laune von Sonnenflecken und RMS, so dass es wahrscheinlich nicht schaden wird, zu explizit zu sein. Es ist sowieso ein guter Ausgangspunkt.
Sdaz MacSkibbons

3
In einem kurzen Überblick über 4.5.2s c-opts.c / opts.c für 'case OPT_W' fehlt: strikter Überlauf, undef, strikter Null-Sentinel, normalisiert, Multichar, implizite Funktionsdeklaration, veraltet, endif-Labels, Kommentar s , eingebautes Makro neu definiert, größer als, größer als Gl., abi. Es ist verrückt, dass es keine Befehlszeilenoption gibt, um sie aufzulisten.
Tony Delroy

3
Ich finde es verrückter, dass -Walles nicht das tut, was man erwarten würde. Aber danke, einige davon sehen sehr nützlich aus!
Sdaz MacSkibbons

1
Das Deaktivieren von Warnungen hat seinen Platz. Immerhin sind sie "Warnungen". Eine andere Situation ist, wenn Sie ein Flag aktivieren, das mehrere Warnungen aktiviert, aber selektiv sein möchten.
Tamás Szelei

1
Wie können Sie verwenden -Waggregate-return? Dies gibt mir eine Warnung für jede Verwendung vonbegin/end()
Flamefire

12

Einige davon sind bereits in -Walloder enthalten -Wextra.

Ein gutes Basis-Setup für C ist:

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

und für C ++

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

(Überspringen -Werrorfür C ++ hat da -Weffc++einige Ärger)


10
-Werror kann für bestimmte Arten von Warnungen deaktiviert werden, zum Beispiel: -Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing

2
ansi : Im C-Modus entspricht dies -std=c89. Im C ++ - Modus entspricht dies -std=c++98. dh wenn Sie eine andere angeben std, verwenden Sie nichtansi
Sean Breckenridge

2

Versuchen

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

Das ist ein schneller und schmutziger Start, der definitiv etwas verbessert werden muss. Selbst wenn Sie den Compiler mit dem für Ihre Sprache geeigneten Namen aufrufen (z. B. g++für C ++), erhalten Sie Warnungen, die für diese Sprache nicht gelten (und der Compiler erhebt die Hände und weigert sich, bis Sie fortzufahren entfernen Sie die Warnung).

Eine andere Sache ist, dass ich hinzugefügt habe -Werror, denn wenn Sie die Warnungen nicht korrigieren, warum ist es Ihnen wichtig, sie einzuschalten? Sie können auch Warnungen aus der Liste entfernen. (Zum Beispiel verwende ich fast nie -Waggregate-returnmit C ++.)

Einige Warnungen werden ohne andere leistungsbezogene Optionen ( -Wstack-protector) nichts bewirken . -fdiagnostics-show-optionund das GCC-Handbuch sind deine Freunde.

Übrigens schließen sich einige Warnungen gegenseitig aus. insbesondere mit -Wtraditionalund -Wold-style-definitionzusammen mit -Werrorwird nicht kompiliert.


0

In der CmakeLists.txt meines Clion

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.