Abgesehen von der Einstellung von -Wall
und der Einstellung von -std=XXX
gibt es noch andere wirklich nützliche, aber weniger bekannte Compiler-Flags, die in C verwendet werden können.
Ich bin besonders an zusätzlichen Warnungen interessiert und/oder und in manchen Fällen Warnungen in Fehler verwandeln, um versehentliche Typunregelmäßigkeiten auf ein Minimum zu reduzieren.
Einige der -f
-Codegenerierungsoptionen sind interessant:
Die -ftrapv
-Funktion führt dazu, dass das Programm bei vorzeichenbehaftetem Integer-Überlauf (formal "undefiniertes Verhalten" in C) abbricht.
-fverbose-asm
ist nützlich, wenn Sie mit -S
kompilieren, um die Assembly-Ausgabe zu untersuchen. Dies fügt einige informative Kommentare hinzu.
-finstrument-functions
fügt Code hinzu, um vom Benutzer bereitgestellte Profilerstellungsfunktionen an jedem Funktionseingabe- und -ausstiegspunkt aufzurufen.
Hier sind meine:
-Wextra
, -Wall
: wesentlich.-Wfloat-equal
: nützlich, weil das Testen von Gleitkommazahlen auf Gleichheit normalerweise schlecht ist.-Wundef
: warn, wenn ein nicht initialisierter Bezeichner in einer #if
-Direktive ausgewertet wird.-Wshadow
: warn, wenn eine lokale Variable eine andere lokale Variable, einen anderen Parameter oder eine globale Variable überschattet oder wenn eine integrierte Funktion gespiegelt wird.-Wpointer-arith
: warn, wenn etwas von der Größe einer Funktion oder von void
abhängt.-Wcast-align
: warn, wenn ein Zeiger so umgewandelt wird, dass die erforderliche Ausrichtung des Ziels erhöht wird. Warnen Sie beispielsweise, wenn ein char *
auf einem int *
auf Maschinen umgewandelt wird, auf die auf Ganzzahlen nur an zwei- oder vier-Byte-Grenzen zugegriffen werden kann.-Wstrict-prototypes
: warn, wenn eine Funktion ohne Angabe der Argumenttypen deklariert oder definiert wird.-Wstrict-overflow=5
: Warnt vor Fällen, in denen der Compiler basierend auf der Annahme optimiert, dass kein signierter Überlauf auftritt. (Der Wert 5 ist möglicherweise zu streng, siehe Handbuchseite.)-Wwrite-strings
: Geben Sie String-Konstanten den Typ const char[
length ]
, damit beim Kopieren der Adresse eines Zeigers in einen nicht-const char *
-Zeiger eine Warnung angezeigt wird.-Waggregate-return
: warn, wenn Funktionen definiert oder aufgerufen werden, die Strukturen oder Vereinigungen zurückgeben.-Wcast-qual
: warn, wenn ein Zeiger umgewandelt wird, um ein Typqualifikationsmerkmal aus dem Zieltyp zu entfernen*.-Wswitch-default
: warn, wenn eine switch
-Anweisung keinen default
-Fall hat*.-Wswitch-enum
: warn, wenn eine switch
-Anweisung einen Index des Aufzählungstyps hat und eine case
für einen oder mehrere der genannten Codes dieser Aufzählung fehlt*.-Wconversion
: warn für implizite Konvertierungen, die einen Wert ändern können*.-Wunreachable-code
: warn, wenn der Compiler feststellt, dass der Code niemals ausgeführt wird*.Die markierten * Manchmal gibt es zu viele falsche Warnungen, daher benutze ich sie nach Bedarf.
Verwenden Sie immer -O
oder höher (-O1
, -O2
, -Os
usw.). Bei der Standardoptimierungsebene verwendet gcc die Kompilierungsgeschwindigkeit und führt nicht genug Analysen durch, um beispielsweise über unitialisierte Variablen zu warnen.
Erwägen Sie, -Werror
-Richtlinien zu erstellen, da Warnungen, die die Kompilierung nicht aufhalten, normalerweise ignoriert werden.
-Wall
aktiviert ziemlich genau die Warnungen, bei denen es sich wahrscheinlich um Fehler handelt.
In -Wextra
enthaltene Warnungen kennzeichnen allgemein gültigen, legitimen Code. Sie können für Codeüberprüfungen nützlich sein (obwohl bei Flint-Programmen viele Fallstricke flexibler sind), würde ich sie jedoch nicht für normale Entwicklung aktivieren.
-Wfloat-equal
ist eine gute Idee, wenn die Entwickler des Projekts Fließkommas nicht kennen, und eine schlechte Idee, wenn sie es sind.
-Winit-self
ist nützlich; Ich frage mich, warum es nicht in -Wuninitialized
enthalten ist.
-Wpointer-arith
ist nützlich, wenn Sie hauptsächlich portablen Code haben, der nicht mit -pedantic
funktioniert.
-save-temps
Dies hinterlässt die Ergebnisse des Präprozessors und der Versammlung.
Die vorverarbeitete Quelle ist zum Debuggen von Makros hilfreich.
Die Assembly ist hilfreich, um festzustellen, welche Optimierungen wirksam wurden. Beispielsweise möchten Sie vielleicht überprüfen, ob GCC bei einigen rekursiven Funktionen eine Endanrufoptimierung durchführt, da Sie sonst möglicherweise den Stack überlaufen lassen.
-fmudflap - fügt allen riskanten Zeigeroperationen Laufzeitüberprüfungen hinzu, um UB abzufangen. Dies immunisiert Ihr Programm wieder effektiv, puffert Überläufe und hilft, alle Arten von baumelnden Zeigern zu fangen.
Hier ist eine Demo:
$ cat mf.c
int main()
{
int a[10];
a[10]=1; // <-- o noes, line 4
}
$ gcc -fmudflap mf.c -lmudflap
$ ./a.out
*******
mudflap violation 1 (check/write): time=1280862302.170759 ptr=0x7fff96eb3d00 size=44
pc=0x7f3a575503c1 location=`mf.c:4:2 (main)'
/usr/lib/libmudflap.so.0(__mf_check+0x41) [0x7f3a575503c1]
./a.out(main+0x90) [0x400a54]
/lib/libc.so.6(__libc_start_main+0xfd) [0x7f3a571e2c4d]
Nearby object 1: checked region begins 0B into and ends 4B after
mudflap object 0xf9c560: name=`mf.c:3:6 (main) a'
bounds=[0x7fff96eb3d00,0x7fff96eb3d27] size=40 area=stack check=0r/3w liveness=3
alloc time=1280862302.170749 pc=0x7f3a57550cb1
number of nearby objects: 1
Ich bin überrascht, dass dies noch niemand gesagt hat - das nützlichste Flag für mich ist -g
, das Debugging-Informationen in die ausführbare Datei einfügt, sodass Sie es debuggen und durch die Quelle springen können (es sei denn, Sie sind kompetent und lesen Assembly und wie der stepi
-Befehl) eines Programms, während es ausgeführt wird.
Nicht wirklich mit C/C++ verwandt, aber trotzdem nützlich:
@file
Setzen Sie alle obigen guten Flags (die Sie alle angegeben haben) in eine 'Datei', und verwenden Sie dieses Flag, um alle Flags in dieser Datei zusammen zu verwenden.
z.B:
Datei: compilerFlags
-Wand
-std = c99
-Wextra
Dann kompilieren Sie:
gcc yourSourceFile @compilerFlags
-march=native
, um optimierten Code für die Plattform (= Chip) zu erstellen, auf der Sie kompilieren
Es ist nicht wirklich hilfreich, um Fehler zu erkennen, aber die selten erwähnte -masm=intel
-Option macht die Verwendung von -S
für die Überprüfung der Assembly-Ausgabe viel viel schöner.
Die AT & T Assembly-Syntax schmerzt meinen Kopf viel zu sehr.
Wenn Sie die Präprozessorflags kennen müssen, die vom Compiler vordefiniert sind:
echo | gcc -E -dM -
Mein Makefile enthält normalerweise
CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
...
g++ $(CFLAGS) -o junk $<
gcc $(CFLAGS) -o [email protected] $<
rm -f junk
Die wichtigsten dieser Optionen wurden bereits besprochen, daher möchte ich auf die beiden Funktionen hinweisen, auf die noch nicht hingewiesen wurde:
Obwohl ich an einer Codebasis arbeite, die muss für die Portabilität auf eine Plattform, die noch keinen anständigen C++ - Compiler hat, ein einfaches C ist, kompiliere ich mit der C++ - Compiler (zusätzlich zum C-Compiler). Das hat 3 Vorteile:
Ja, ich bin eine hoffnungslos optimistische Pollyanna, die immer wieder denkt, dass sicherlich jeden Monat eine Plattform entweder für veraltet erklärt wird oder einen anständigen C++ - Compiler erhält und wir endlich zu C++ wechseln können. Meiner Meinung nach ist dies unvermeidlich - die einzige Frage ist, ob dies geschieht, bevor oder nachdem das Management schließlich jedem ein Pony ausstellt. :-)
Hier ist eine großartige Flagge, die nicht erwähnt wurde:
-Werror-implicit-function-declaration
Geben Sie einen Fehler ein, wenn eine Funktion verwendet wird, bevor Sie deklariert werden.
-Wstrict-prototypes -Wmissing-prototypes
man gcc
Das Handbuch enthält viele interessante Flaggen mit guten Beschreibungen. Allerdings wird -Wall GCC wahrscheinlich so ausführlich wie möglich machen. Wenn Sie weitere interessante Daten wünschen, sollten Sie einen Blick auf valgrind oder ein anderes Tool zur Fehlerprüfung werfen.
Es gibt -Werror
, der alle Warnungen als Fehler behandelt und die Kompilierung stoppt. Die gcc
-Handbuchseite erläutert jeden Befehlszeilenschalter für Ihren Compiler.
Nun, -Wextra
sollte auch Standard sein. -Werror
verwandelt Warnungen in Fehler (was sehr nervig sein kann, insbesondere wenn Sie ohne -Wno-unused-result
kompilieren). -pedantic
in Kombination mit std=c89
gibt zusätzliche Warnmeldungen aus, wenn Sie C99-Funktionen verwenden.
Aber das war es schon. Sie können einen C-Compiler nicht in etwas mehr Typ-Save als C selbst abstimmen.
-M*
Familie von Optionen.
Damit können Sie Make-Dateien schreiben, die automatisch herausfinden, von welchen Header-Dateien Ihre C- oder C++ - Quelldateien abhängen sollen. GCC generiert Make-Dateien mit diesen Abhängigkeitsinformationen und schließt sie dann aus Ihrer primären Make-Datei ein.
Hier ein Beispiel für ein extrem generisches Makefile mit -MD und -MP, das ein Verzeichnis mit C++ - Quell- und Header-Dateien kompiliert und alle Abhängigkeiten automatisch ermittelt:
CPPFLAGS += -MD -MP
SRC = $(wildcard *.cpp)
my_executable: $(SRC:%.cpp=%.o)
g++ $(LDFLAGS) -o [email protected] $^
-include $(SRC:%.cpp=%.d)
Hier ist ein Blog-Post, der ausführlicher darauf eingeht: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html
-Wfloat-equal
Von: http://mces.blogspot.com/2005/07/char-const-argv.html
Eine der anderen neuen Warnungen, die ich mag, ist der -float-egal. Dieser warnt, wenn Sie eine Gleitkommazahl unter Gleichheitsbedingungen haben. Das ist großartig! Wenn Sie alle eine Computergrafik oder einen (noch schlimmer :) Algorithmus für die Berechnungsgeometrie programmiert haben, wissen Sie, dass keine zwei Schwimmer mit der Gleichheit übereinstimmen ...
Ich fand diesen Thread auf der Suche nach einer Flagge, um ein bestimmtes Problem zu beheben. Ich sehe es hier nicht, also füge ich eine hinzu, die mich nur auf mein Post :
Das -Wformat=2
-Flag
-Wformat
=> Überprüfen Sie die Aufrufe vonprintf
undscanf
usw., um sicherzustellen, dass die angegebenen Argumente über Typen verfügen, die der angegebenen Formatzeichenfolge entsprechen ...
Und der wirklich wichtige Teil ( laut GCC-Handbuch ):
-Wformat
ist in-Wall
enthalten. Zur besseren Kontrolle einiger Aspekte der Formatprüfung stehen die Optionen-Wformat-y2k
,-Wno-format-extra-args
,-Wno-format-zero-length
,-Wformat-nonliteral
,-Wformat-security
und-Wformat=2
zur Verfügung, sind jedoch nicht in der Option "Wall" enthalten
Nur weil Sie -Wall
haben, heißt das nicht, dass Sie alles haben. ;)
Ich benutze manchmal -s
für eine viel kleinere ausführbare Datei:
-s
Remove all symbol table and relocation information from the executable.
Quelle: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
Diese Antwort mag zwar etwas unrealistisch sein und die Frage ist von mir +1 wert, da
Ich bin besonders an zusätzlichen Warnungen interessiert und/oder und in manchen Fällen Warnungen in Fehler verwandeln, um versehentliche Typunregelmäßigkeiten auf ein Minimum zu reduzieren.Es gibt ein Tool, das ALLE Fehler und mögliche Fehler herausfinden sollte, die möglicherweise nicht offensichtlich sind. Es gibt Splint , für das IMHO eine bessere Aufgabe beim Ermitteln von Fehlern im Vergleich zu gcc oder einem anderen Compiler darstellt diese Angelegenheit. Das ist ein würdiges Werkzeug in Ihrer Werkzeugkiste.
Die statische Überprüfung mit einem fusselartigen Werkzeug wie der Schiene sollte Teil einer Compiler-Toolchain sein.
Ich bin besonders an weiteren Warnungen interessiert.
Zusätzlich zu -Wall
unterstützt die Option -W
oder -Wextra
(-W
funktioniert sowohl mit älteren als auch mit neueren Versionen von gcc; neuere Versionen unterstützen den alternativen Namen -Wextra
, der dasselbe bedeutet, ist jedoch beschreibender) verschiedene zusätzliche Warnungen.
Es gibt auch noch mehr Warnungen, die von keiner der beiden aktiviert werden, im Allgemeinen für Dinge, die fragwürdiger sind. Die verfügbaren Optionen hängen davon ab, welche gcc-Version Sie verwenden. Weitere Informationen finden Sie in man gcc
oder info gcc
. Weitere Informationen finden Sie in der Online-Dokumentation für die jeweilige gcc-Version, die Sie interessieren. -pedantic
gibt alle von der bestimmter Standard (der von anderen Optionen wie -std=xxx
oder -ansi
abhängig ist) und beschwert sich über die Verwendung von gcc-Erweiterungen.
und/oder und verwandeln Warnungen in einigen Fällen in Fehler, um jeden versehentlichen Typ auf ein Minimum zu reduzieren Nichtübereinstimmungen.
-Werror
verwandelt alle Warnungen in Fehler. Ich denke nicht, dass Sie mit gcc das selektiv für bestimmte Warnungen machen können.
Sie werden wahrscheinlich feststellen, dass Sie auswählen müssen, welche Warnungen pro Projekt aktiviert werden sollen (insbesondere wenn Sie -Werror
verwenden), da Headerdateien aus externen Bibliotheken einige davon auslösen können. (Insbesondere -pedantic
ist meiner Erfahrung nach in dieser Hinsicht wenig hilfreich.)
-Wmissing-prototypes
: Wenn eine globale Funktion ohne vorherige Prototypdeklaration definiert ist.-Wformat-security
: Warnt vor der Verwendung von Formatfunktionen, die mögliche Sicherheitsprobleme darstellen. Derzeit warnt dies vor Aufrufen von printf
- und scanf
-Funktionen, bei denen der Formatstring kein String-Literal ist und keine Formatargumente vorhanden sind-Werror=return-type
: Fehler erzwingen, wenn die Funktion in gcc keine Rückgabe hat
-Werror=implicit-function-declaration
: Fehler erzwingen, wenn die Funktion ohne definiert/nicht verwendet wird