it-swarm.com.de

Flags, um gründliche und ausführliche g ++ - Warnungen zu ermöglichen

In C unter gcc beginne ich oft mit dem folgenden Satz von Warnflags (der aus mehreren Quellen zusammengestellt wurde):

-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 baue (zumindest meine Debug-Versionen) mit diesen Warnungen auf und repariere alles, was ich kann (normalerweise alles), und entferne Flags nur dann, wenn sie entweder nicht relevant oder nicht fixierbar sind (fast nie). Manchmal füge ich auch -Werror hinzu, wenn ich beim Kompilieren einen Schritt zurücktreten muss.

Ich greife gerade C++ auf (ja, ich bin 15 Jahre hinter den Zeiten zurück) und ich möchte mit dem rechten Fuß beginnen.

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

104

D'oh, bei all meinen ursprünglichen Suchen waren 99% der Beiträge zu suppress Warnungen (fast genug) aufgetaucht, aber ich bin gerade über diesen Kommentar gestoßen, der diese schönen Flaggen enthält (einige weniger relevant):

Kreuz geprüft 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 Betrogener war, aber zumindest war es tief begraben. :-)

35

Ich ging durch und fand den minimalen Satz von Einschlüssen, der die maximale Warnstufe erhalten sollte. Ich habe dann die Warnungen aus dieser Liste entfernt, die meines Erachtens nicht darauf hinweisen, dass etwas Schlimmes passiert, oder zu viele False Positives, um in einem echten Build verwendet zu werden. Ich bemerkte, warum jeder der von mir ausgeschlossenen ausgeschlossen wurde. Dies ist mein letzter Satz vorgeschlagener 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

Vorhandene fragwürdige Warnungen:

  • Ich füge -Wno-unused hinzu, weil ich oft Variablen habe, von denen ich weiß, dass sie ich später verwenden werde, für die ich jedoch noch nicht die Funktionalität geschrieben habe. Wenn ich Warnungen darüber entferne, 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-optimization scheint eine starke Benutzereinstellung zu sein. Ich habe gerade dieses zu meinem Build hinzugefügt (nur für optimierte Builds aus offensichtlichen Gründen) und es hat sich nichts ergeben, daher scheint es keine besonders gesprächige Warnung zu sein, zumindest was die Art und Weise betrifft, wie ich programmiere. Ich füge es ein (auch wenn Code, der diese Warnung auslöst, nicht unbedingt falsch ist), weil ich daran glaube, mit meinen Tools zu arbeiten, anstatt gegen sie vorzugehen. Wenn mir gcc sagt, dass es den Code nicht so optimieren kann, wie ich ihn geschrieben habe, sollte ich mir überlegen, ihn neu zu schreiben. Ich vermute, dass Code, der diese Warnung auslöst, davon profitieren könnte, modularer zu sein. Obwohl der Code also technisch (wahrscheinlich) nicht falsch ist, ist er stilistisch wahrscheinlich.

  • -Wfloat-equal warnt vor sicheren Gleichheitsvergleichen (insbesondere vor einem Vergleich mit einem nicht berechneten Wert von -1). Ein Beispiel in meinem Code, in dem ich dies verwende, ist, dass ich einen Vektor von float habe. Ich gehe diesen Vektor durch und es gibt einige Elemente, die ich noch nicht beurteilen 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 in Gleitkommazahlen ist wahrscheinlich ein Fehler. Deshalb füge ich sie in die Standardliste ein.

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

  • -Wsign-conversion war eine schwierige Frage (und hätte es fast nicht geschafft, auf die Liste zu kommen). Das Aktivieren in meinem Code erzeugte eine große Menge 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 normalerweise eine leichte Effizienzsteigerung mit vorzeichenlosen Werten erzielen würde, da ich eine große Anzahl von ganzzahligen Divisionen durchführe. Ich habe diese Effizienz geopfert, weil ich befürchtet hatte, aus Versehen eine vorzeichenbehaftete Ganzzahl in eine vorzeichenlose umzuwandeln und dann zu dividieren (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 Besetzungen hinzufügen. Es ist derzeit etwas schwierig zu bedienen, da die Warnung nicht so klug ist. Wenn Sie beispielsweise unsigned short + (integral constant expression) ausführen, wird dieses Ergebnis implizit zu int heraufgestuft. Es warnt dann vor einem möglichen Vorzeichenproblem, wenn Sie diesen Wert unsigned oder unsigned short zuweisen, obwohl er sicher ist. Dies ist definitiv die optionalste Warnung für fast alle Benutzer.

  • -Wsign-promo: siehe -Wsign-conversion.

  • -Wswitch-default erscheint sinnlos (Sie möchten nicht immer einen Standardfall, wenn Sie alle Möglichkeiten explizit aufgezählt haben). Wenn Sie diese Warnung jedoch aktivieren, ist dies wahrscheinlich eine gute Idee. In Fällen, in denen Sie alles außer den aufgeführten Möglichkeiten explizit ignorieren möchten (andere Zahlen sind jedoch möglich), geben Sie default: break; ein, 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) angeben, um sicherzustellen, dass Sie tatsächlich alle möglichen Optionen abgedeckt haben. Damit können Sie genau bestimmen, in welchem ​​Bereich sich Ihr Problem befindet, und dies wird programmgesteuert erzwungen. Sie müssen jedoch vorsichtig sein, wenn Sie überall nur die Behauptung (falsch) festhalten. Es ist besser, als mit dem Standardfall nichts zu tun, aber wie bei assert üblich, wird es in Release-Builds nicht funktionieren. Mit anderen Worten, Sie können sich nicht darauf verlassen, dass Zahlen validiert werden, die Sie beispielsweise über eine Netzwerkverbindung oder eine Datenbank erhalten, über die Sie keine absolute Kontrolle haben. Ausnahmen oder eine frühzeitige Rückkehr sind die beste Möglichkeit, dies zu beheben (Sie müssen jedoch immer noch einen Standardfall haben!).

  • -Werror ist wichtig für mich. Wenn Sie große Mengen an Code in einem Multithread-Build mit mehreren Zielen kompilieren, kann eine Warnung leicht übersehen werden. Warnungen in Fehler zu verwandeln 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, warum ich sie nicht in die Standardliste aufgenommen habe:

Warnungen, die fehlen:

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

  • -Waggregate-return ist nichts, was ich als Fehler betrachte. Es wird beispielsweise ausgelöst, wenn eine bereichsbasierte for-Schleife für einen Vektor von Klassen verwendet wird. Bei der Rückgabewertoptimierung sollten negative Auswirkungen berücksichtigt werden.

  • -Wconversion wird für diesen Code ausgelöst: 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. In vielen Fällen tue ich dies absichtlich nicht, sodass die Warnungen zu unübersichtlich sind, um nützlich zu sein. Es ist jedoch hilfreich, gelegentlich zu aktivieren und nach anderen Warnungen zu suchen (z. B. nach nicht virtuellen Destruktoren von Basisklassen). Dies wäre nützlicher als eine Sammlung von Warnungen (wie -Wall) anstelle einer einzelnen Warnung für sich.

  • -Winline fehlt, weil ich das Schlüsselwort inline nicht für Optimierungszwecke verwende, sondern nur, um Funktionen in Kopfzeilen zu definieren. Es ist mir egal, ob das Optimierungsprogramm es tatsächlich einfügt. Diese Warnung beklagt sich auch, wenn eine in einem Klassentext deklarierte Funktion (z. B. ein leerer virtueller Destruktor) nicht eingebunden werden kann.

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

  • -Wmissing-format-attribute wird nicht verwendet, da ich keine Gnu-Erweiterungen verwende. Gleiches gilt für -Wsuggest-attribute und mehrere andere

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

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

  • -Wpadded wird gelegentlich aktiviert, um das Layout von Klassen zu optimieren. Es wird jedoch nicht aktiviert, da nicht alle Klassen über genügend Elemente verfügen, um am Ende die Auffüllung zu entfernen. Theoretisch könnte ich einige zusätzliche Variablen für 'free' bekommen, aber es ist den zusätzlichen Aufwand nicht wert, dies beizubehalten (wenn sich meine Klassengröße ändert, ist es nicht einfach, diese zuvor freien Variablen zu entfernen).

  • -Wstack-protector wird nicht verwendet, da ich -fstack-protector nicht verwende

  • -Wstrict-aliasing=3 wird von -Wall aktiviert und ist am genauesten, aber es sieht so aus, als ob Stufe 1 und 2 mehr Warnungen geben. Theoretisch ist eine niedrigere Stufe eine "stärkere" Warnung, jedoch auf Kosten von mehr Fehlalarmen. Mein eigener Testcode sauber kompiliert unter allen 3 Ebenen.

  • -Wswitch-enum ist nicht das Verhalten, das ich will. Ich möchte nicht jede switch-Anweisung explizit behandeln. Es wäre nützlich, wenn die Sprache über einen Mechanismus verfügen würde, um dies bei bestimmten switch-Anweisungen zu aktivieren (um sicherzustellen, dass zukünftige Änderungen an der Aufzählung überall dort vorgenommen werden, wo sie vorgenommen werden müssen), aber es ist übertrieben für eine "Alles-oder-Nichts" -Einstellung.

  • -Wunsafe-loop-optimizations verursacht 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 ihnen eine Reihe von Funktionen zuzuweisen (mithilfe der bereichsbasierten for-Schleife). Dies 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-constant und -Wuseless-cast sind reine GCC-4.7-Warnungen, die ich beim Übergang zu GCC 4.7 hinzufüge.

Ich habe als Ergebnis einiger Untersuchungen einige Fehlerberichte/Verbesserungsvorschläge bei gcc eingereicht, sodass ich hoffentlich in der Lage sein werde, der Liste "Einschließen" mehr Warnungen aus der Liste "Nicht einschließen" hinzuzufügen . Diese Liste enthält alle in diesem Thread erwähnten Warnungen (plus 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 irgendwelche Warnungen bemerkt, die von diesem Beitrag völlig 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)

119
David Stone

Einige davon sind bereits in -Wall oder -Wextra enthalten.

Eine gute Grundeinstellung für C ist:

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

und für C++

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

(-Werror für C++ überspringen, da -Weffc++ einige Störungen hat)

11
Let_Me_Be

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 ein wenig Tuning erfordert; Selbst wenn Sie den Compiler mit dem entsprechenden Namen für Ihre Sprache aufrufen (z. B. g++ für C++), erhalten Sie Warnungen, die sich nicht auf diese Sprache beziehen (und der Compiler gibt seine Hände hoch und lehnt ab, fortzufahren Sie entfernen die Warnung).

Eine andere Sache ist, dass ich -Werror hinzugefügt habe. Wenn Sie die Warnungen nicht korrigieren, warum sollten Sie sie dann einschalten? Sie können auch Warnungen aus der Liste entfernen. (Zum Beispiel verwende ich -Waggregate-return fast nie mit C++.)

Einige Warnungen können ohne andere leistungsbezogene Optionen (-Wstack-protector) nichts ausrichten. -fdiagnostics-show-option und das GCC-Handbuch sind Ihre Freunde.

Einige Warnungen schließen sich gegenseitig aus. Insbesondere die Verwendung von -Wtraditional und -Wold-style-definition zusammen mit -Werror wird nicht kompiliert.

2

In der CmakeLists.txt meines Clions

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)
0
snr