web-dev-qa-db-fra.com

Drapeaux GCC utiles pour C

Au-delà de la définition de -Wall et de la définition de -std=XXX, quels autres indicateurs de compilateur utiles, mais moins connus, existent-ils pour une utilisation en C?

Je suis particulièrement intéressé par tout avertissement supplémentaire, et/ou par transformer ces avertissements en erreurs dans certains cas, afin de minimiser absolument toute inadéquation de type accidentelle.

148
Matt Joiner

Plusieurs options de génération de code -f sont intéressantes:

  • La fonction -ftrapv provoquera l’abandon du programme en cas de dépassement d’entier signé (formellement "comportement non défini" en C).

  • -fverbose-asm est utile si vous compilez avec -S pour examiner le résultat de l’Assembly. Il ajoute des commentaires informatifs.

  • -finstrument-functions ajoute du code pour appeler les fonctions de profilage fournies par l'utilisateur à chaque entrée et point de sortie de fonction.

63
caf

Voici les miens:

  • -Wextra, -Wall: essentiel.
  • -Wfloat-equal: utile car le test de l'égalité des nombres en virgule flottante est généralement incorrect.
  • -Wundef: avertir si un identifiant non initialisé est évalué dans une directive #if.
  • -Wshadow: avertit chaque fois qu'une variable locale masque une autre variable locale, un paramètre ou une variable globale, ou lorsqu'une fonction intégrée est masquée.
  • -Wpointer-arith: avertit si quelque chose dépend de la taille d'une fonction ou de void.
  • -Wcast-align: avertit chaque fois qu'un pointeur est converti de telle sorte que l'alignement requis de la cible soit augmenté. Par exemple, avertissez si un char * est converti en un int * sur des ordinateurs où les entiers ne sont accessibles qu'aux limites de deux ou quatre octets.
  • -Wstrict-prototypes: avertir si une fonction est déclarée ou définie sans spécifier les types d'argument.
  • -Wstrict-overflow=5: avertit des cas où le compilateur optimise en se basant sur l'hypothèse que le débordement signé ne se produit pas. (La valeur 5 est peut-être trop stricte, voir la page de manuel.)
  • -Wwrite-strings: donnez aux constantes de chaîne le type const char[ length ] afin que la copie de l'adresse de l'un dans un pointeur autre que const char * reçoive un avertissement.
  • -Waggregate-return: avertit si des fonctions renvoyant des structures ou des unions sont définies ou appelées.
  • -Wcast-qual: avertir chaque fois qu'un pointeur est converti pour supprimer un qualificatif de type du type cible*.
  • -Wswitch-default: avertir chaque fois qu'une instruction switch n'a pas de casse default*.
  • -Wswitch-enum: avertir chaque fois qu'une instruction switch a un index de type énuméré et qu'il manque une case pour un ou plusieurs des codes nommés de cette énumération*.
  • -Wconversion: warning pour les conversions implicites pouvant altérer une valeur*.
  • -Wunreachable-code: avertir si le compilateur détecte que le code ne sera jamais exécuté*.

Ceux marqués * donne parfois trop d’avertissements fallacieux, aussi je les utilise au besoin.

132
Alok Singhal

Utilisez toujours -O ou supérieur (-O1, -O2, -Os, etc.). Au niveau d’optimisation par défaut, gcc recherche la vitesse de compilation et ne fait pas assez d’analyses pour se mettre en garde contre des variables telles que les variables unitisées.

Envisagez de définir une stratégie -Werror, car les avertissements qui n'arrêtent pas la compilation ont tendance à être ignorés.

-Wall active les avertissements qui risquent fort d'être des erreurs.

Les avertissements inclus dans -Wextra ont tendance à signaler un code commun et légitime. Ils peuvent être utiles pour les revues de code (bien que les programmes de type lint trouvent de plus en plus de pièges plus flexibles), mais je ne les activerais pas pour un développement normal.

-Wfloat-equal est une bonne idée si les développeurs du projet ne connaissent pas la virgule flottante et une mauvaise idée s’ils le sont.

-Winit-self est utile; Je me demande pourquoi ce n'est pas inclus dans -Wuninitialized.

-Wpointer-arith est utile si vous avez un code principalement portable qui ne fonctionne pas avec -pedantic.

50
Gilles
-save-temps

Cela laisse derrière les résultats du préprocesseur et de l’Assemblée.

La source prétraitée est utile pour le débogage de macros.

L'Assemblée est utile pour déterminer les optimisations entrées en vigueur. Par exemple, vous voudrez peut-être vérifier que GCC optimise les appels en aval sur certaines fonctions récursives, sans quoi vous pourriez potentiellement déborder de la pile.

37
catphive

-fmudflap - ajoute des contrôles d'exécution à toutes les opérations de pointeur risquées pour attraper UB. Cela immunise efficacement votre programme à nouveau contre les débordements de mémoire tampon et aide à attraper toutes sortes de pointeurs pendants. 

Voici une démo: 

$ 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
Nordic Mainframe

Je suis surpris que personne ne l'ait encore dit. L'indicateur le plus utile en ce qui me concerne est -g, qui place les informations de débogage dans l'exécutable de manière à ce que vous puissiez les déboguer et parcourir la source (à moins que vous ne maîtrisiez bien lire. et comme la commande stepi) d’un programme en cours d’exécution.

35
user257111

Pas vraiment lié au C/C++, mais utile quand même:

@file

Mettez tous les bons indicateurs ci-dessus (que vous avez tous spécifiés) dans un "fichier" et utilisez cet indicateur pour utiliser tous les indicateurs de ce fichier ensemble.

par exemple:

Fichier: compilerFlags

-Mur

-std = c99

-Wextra

Puis compiler:

gcc yourSourceFile @compilerFlags
18
Amit Tomar

-march=native pour produire du code optimisé pour la plate-forme (= puce) sur laquelle vous compilez

15
Jens Gustedt

Ce n'est pas vraiment utile pour détecter les erreurs, mais l'option -masm=intel, rarement mentionnée, facilite grandement l'utilisation de -S pour inspecter la sortie de l'assembly.

La syntaxe de AT & T Assembly me fait trop mal à la tête.

13
Michael Burr

Si vous avez besoin de connaître les indicateurs de préprocesseur prédéfinis par le compilateur:

echo | gcc -E -dM -
13
sizzzzlerz

Mon makefile contient généralement

  CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
  ...
  g++ $(CFLAGS) -o junk $<
  gcc $(CFLAGS) -o $@ $<
  rm -f junk

Les plus importantes de ces options ont déjà été discutées, je vais donc souligner les deux caractéristiques qui n’ont pas encore été signalées:

Même si je travaille sur une base de code qui doit être simple, la portabilité sur une plate-forme qui encore n'a pas de compilateur C++ décent, je fais une compilation "supplémentaire" avec le C++. compilateur (en plus du compilateur C). Cela a 3 avantages: 

  1. le compilateur C++ me donne parfois de meilleurs messages d'avertissement que le compilateur C. 
  2. Le compilateur C++ accepte l'option -Weffc ++, qui me donne parfois des astuces utiles, que je manquerais si je ne les compilais qu'en C simple. 
  3. Je peux garder le code relativement facile à porter en C++, en évitant quelques conditions limites où le code en clair C est un code C++ non valide (comme la définition d'une variable nommée "bool").

Oui, je suis une Pollyanna désespérément optimiste qui continue de penser que sûrement chaque mois maintenant, une plate-forme sera déclarée obsolète ou gagnera un compilateur C++ décent et nous pourrons enfin basculer vers C++. Dans mon esprit, c'est inévitable - la seule question à se poser est de savoir si cela se produit avant ou après que la direction ait finalement délivré un poney à tout le monde. :-)

10
David Cary

Voici un grand drapeau qui n'a pas été mentionné:

-Werror-implicit-function-declaration

Donne une erreur chaque fois qu'une fonction est utilisée avant d'être déclarée.

9
Matt Joiner
-Wstrict-prototypes -Wmissing-prototypes
9
ninjalj
man gcc

Le manuel est plein de drapeaux intéressants avec de bonnes descriptions. Cependant, -Wall rendra probablement gcc aussi verbeux que possible. Si vous voulez des données plus intéressantes, vous devriez jeter un œil à valgrind ou à un autre outil permettant de vérifier les erreurs.

8
Johan

Il existe -Werror, qui traite tous les avertissements comme des erreurs et arrête la compilation. La page de manuel gcc explique chaque commutateur de ligne de commande pour votre compilateur.

6
Greg Hewgill

-Wextra devrait également être standard. -Werror transforme les avertissements en erreurs (qui peuvent être très ennuyeuses, surtout si vous compilez sans -Wno-unused-result). -pedantic en combinaison avec std=c89 vous donne des avertissements supplémentaires si vous utilisez les fonctionnalités de C99.

Mais c'est à peu près tout. Vous ne pouvez pas accorder un compilateur C à quelque chose de plus économique que C lui-même.

6
RWS

-M* famille d'options.

Celles-ci vous permettent d'écrire des fichiers make qui déterminent automatiquement les fichiers d'en-tête sur lesquels doivent dépendre vos fichiers source c ou c ++. GCC générera des fichiers make avec ces informations de dépendance, puis vous les incluerez de votre fichier make primaire.

Voici un exemple de fichier makefile extrêmement générique utilisant -MD et -MP qui compilera un répertoire plein de fichiers source et d'en-tête c ++ et déterminera automatiquement toutes les dépendances:

CPPFLAGS += -MD -MP                                         
SRC = $(wildcard *.cpp)                                                       

my_executable: $(SRC:%.cpp=%.o)                                                        
        g++ $(LDFLAGS) -o $@ $^                                               

-include $(SRC:%.cpp=%.d)

Voici un article de blog qui en parle plus en profondeur: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html

5
catphive

-Wfloat-equal

De: http://mces.blogspot.com/2005/07/char-const-argv.html

L'un des autres nouveaux avertissements que j'aime bien est le -Wfloat-equal. Celui-ci vous avertit chaque fois que vous avez un nombre à virgule flottante dans une condition d'égalité. C'est brillant! Si vous avez tous programmé un graphisme ou (pire) un algorithme de géométrie de calcul, vous savez qu'il n'y a jamais deux flottants qui correspondent avec l'égalité ...

4
stud

J'ai trouvé ce fil qui cherchait un drapeau pour résoudre un problème spécifique. Je ne le vois pas ici, donc je vais en ajouter un qui m'agace juste sur my post :

Le drapeau -Wformat=2 

-Wformat => Vérifiez les appels à printf et scanf, etc., pour vous assurer que les arguments fournis ont des types appropriés à la chaîne de format spécifiée ...

Et la partie la plus importante à ce sujet ( selon le manuel GCC ):

-Wformat est inclus dans -Wall. Pour plus de contrôle sur certains aspects de la vérification du format, les options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security et -Wformat=2 sont disponibles, mais ne sont pas incluses dans -Wall.`

Donc, ce n'est pas parce que vous avez -Wall que vous avez tout. ;)

4
Mike

J'utilise parfois -s pour un exécutable beaucoup plus petit:

-s
    Remove all symbol table and relocation information from the executable.

Source: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options

3
Vasiliy Sharapov

Bien que cette réponse soit un peu hors sujet et que la question mérite un +1 de ma part, car 

Je suis particulièrement intéressé par tout avertissement supplémentaire, et/ou par transformer ces avertissements en erreurs dans certains cas, afin de minimiser absolument toute inadéquation de type accidentelle.
il y a un outil qui devrait piéger TOUTES LES erreurs et erreurs potentielles qui ne sont peut-être pas évidentes, il y a splint dont IMHO fait un meilleur travail pour attraper les erreurs par rapport à gcc ou à tout autre compilateur. cela importe. C'est un outil digne d'avoir dans votre coffre à outils. 

La vérification statique à l'aide d'un outil de type charpie, tel qu'une attelle, aurait dû faire partie d'une chaîne d'outils du compilateur.

3
t0mm13b

Je suis particulièrement intéressé par des avertissements supplémentaires,

En plus de -Wall, l'option -W ou -Wextra (-W fonctionne avec les anciennes versions de gcc ainsi que les plus récentes; les versions plus récentes prennent en charge le nom alternatif -Wextra, qui signifie la même chose, mais est plus descriptif) active divers avertissements supplémentaires.

Il y a aussi encore plus d'avertissements qui ne sont activés par aucun de ceux-ci, généralement pour des choses plus discutablement mauvaises. L’ensemble des options disponibles dépend de la version de gcc que vous utilisez - consultez man gcc ou info gcc pour plus de détails, ou consultez la documentation en ligne pour la version de gcc particulière qui vous intéresse. Et -pedantic émet tous les avertissements requis par le norme particulière utilisée (qui dépend d’autres options telles que -std=xxx ou -ansi) et se plaint de l’utilisation des extensions gcc.

et/ou et transformer les avertissements en erreurs dans certains cas afin de minimiser absolument tout type accidentel inadéquations.

-Werror transforme tous les avertissements en erreurs. Je ne pense pas que gcc vous laisse faire cela de manière sélective pour des avertissements particuliers, cependant.

Vous constaterez probablement que vous devez sélectionner de manière sélective les avertissements activés projet par projet (surtout si vous utilisez -Werror), car les fichiers d'en-tête de bibliothèques externes peuvent en dérouter certains. (-pedantic en particulier a tendance à ne pas être utile à cet égard, selon mon expérience.)

2
Matthew Slattery
  • -Wmissing-prototypes: Si une fonction globale est définie sans déclaration de prototype précédente.
  • -Wformat-security: avertit des utilisations des fonctions de format qui représentent d'éventuels problèmes de sécurité. Actuellement, cela met en garde sur les appels aux fonctions printf et scanf où la chaîne de format n'est pas un littéral de chaîne et où il n'y a pas d'argument de format.
0
Praveen Handigol
  • -Werror=return-type: applique une erreur lorsque la fonction n'a pas de retour dans gcc

  • -Werror=implicit-function-declaration: applique une erreur lorsque la fonction est utilisée sans être défini/non inclus

0
HaxtraZ