web-dev-qa-db-de.com

Nützliche GCC-Flags für C

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.

148
Matt Joiner

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.

63
caf

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.

132
Alok Singhal

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.

50
Gilles
-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.

37
catphive

-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
35

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.

35
user257111

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
18
Amit Tomar

-march=native, um optimierten Code für die Plattform (= Chip) zu erstellen, auf der Sie kompilieren

15
Jens Gustedt

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.

13
Michael Burr

Wenn Sie die Präprozessorflags kennen müssen, die vom Compiler vordefiniert sind:

echo | gcc -E -dM -
13
sizzzzlerz

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:

  1. der C++ - Compiler gibt mir gelegentlich bessere Warnmeldungen als der C-Compiler.
  2. Der C++ - Compiler akzeptiert die Option -Weffc ++, die mir gelegentlich einige nützliche Tipps gibt, die ich verpassen würde, wenn ich sie nur in C kompilieren würde.
  3. Ich kann den Code relativ einfach nach C++ portieren, um einige Randbedingungen zu vermeiden, bei denen einfacher C-Code ungültiger C++ - Code ist (z. B. das Definieren einer Variablen namens "bool").

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. :-)

10
David Cary

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.

9
Matt Joiner
-Wstrict-prototypes -Wmissing-prototypes
9
ninjalj
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.

8
Johan

Es gibt -Werror, der alle Warnungen als Fehler behandelt und die Kompilierung stoppt. Die gcc-Handbuchseite erläutert jeden Befehlszeilenschalter für Ihren Compiler.

6
Greg Hewgill

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.

6
RWS

-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

5
catphive

-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 ...

4
stud

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 von printf und scanf 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. ;)

4
Mike

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

3

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.

3
t0mm13b

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.)

2
  • -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
0
  • -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

0
HaxtraZ