help - Banderas de GCC útiles para C
gcc help (23)
Más allá de configurar -Wall
, y establecer -std=XXX
, ¿qué otras banderas del compilador realmente útiles, pero menos conocidas, están ahí para su uso en C?
Estoy particularmente interesado en advertencias adicionales, y / o convirtiendo advertencias en errores en algunos casos para minimizar absolutamente cualquier desajuste de tipos accidentales.
Estoy particularmente interesado en cualquier advertencia adicional,
Además de -Wall
, la opción -W
o -Wextra
( -W
funciona con versiones anteriores de gcc y más nuevas; las versiones más recientes admiten el nombre alternativo -Wextra
, que significa lo mismo, pero es más descriptivo) habilita varias advertencias adicionales.
También hay aún más advertencias que no están habilitadas por ninguna de esas personas, generalmente para cosas que son más cuestionablemente malas. El conjunto de opciones disponibles depende de la versión de gcc que esté utilizando; consulte man gcc
o info gcc
para obtener más información, o consulte la gcc.gnu.org/onlinedocs para la versión de gcc particular que le interese. Y -pedantic
emite todas las advertencias requeridas por el particular estándar que se usa (que depende de otras opciones como -std=xxx
o -ansi
) y se queja sobre el uso de extensiones gcc.
y / o convirtiendo advertencias en errores en algunos casos para minimizar absolutamente cualquier desajuste de tipo accidental.
-Werror
convierte todas las advertencias en errores. Sin embargo, no creo que gcc te permita hacer eso de forma selectiva para advertencias particulares.
Probablemente descubra que debe ser selectivo con respecto a las advertencias que están habilitadas por proyecto (especialmente si usa -Werror
), ya que los archivos de encabezado de las bibliotecas externas pueden -Werror
algunas de ellas. (En mi experiencia, el -pedantic
en particular tiende a ser inútil en este sentido).
-Withsing-prototypes: si una función global se define sin una declaración previa de prototipo. -What-security: advierte sobre los usos de las funciones de formato que representan posibles problemas de seguridad. En la actualidad, esto advierte sobre las llamadas a funciones printf y scanf donde la cadena de formato no es una cadena literal y no hay argumentos de formato
A veces uso -s
para un ejecutable mucho más pequeño:
-s
Remove all symbol table and relocation information from the executable.
Fuente: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
Aquí están los míos:
-
-Wextra
,-Wall
: esencial. -
-Wfloat-equal
: útil porque generalmente probar los números de punto flotante para la igualdad es malo. -
-Wundef
: advierte si un identificador no inicializado se evalúa en una directiva#if
. -
-Wshadow
: avisa cada vez que una variable local sombrea otra variable local, parámetro o variable global o siempre que se-Wshadow
una función incorporada. -
-Wpointer-arith
: advierte si algo depende del tamaño de una función o de unvoid
. -
-Wcast-align
: advierte cada vez que se lanza un puntero de manera que se aumenta la alineación requerida del objetivo. Por ejemplo, advierta si unchar *
se convierte aint *
en máquinas donde solo se puede acceder a enteros en límites de dos o cuatro bytes. -
-Wstrict-prototypes
: advierte si una función se declara o define sin especificar los tipos de argumentos. -
-Wstrict-overflow=5
: advierte sobre casos en los que el compilador optimiza en base a la suposición de que no se produce el desbordamiento firmado. (El valor 5 puede ser demasiado estricto, consulte la página del manual). -
-Wwrite-strings
: le da a las constantes de cadena el tipoconst char[
length]
para que la copia de la dirección de uno en un puntero noconst char *
reciba una advertencia. -
-Waggregate-return
: advierte si se definen o llaman funciones que devuelven estructuras o uniones. -
-Wcast-qual
: avisa cada vez que se lanza un puntero para eliminar un calificador de tipo del tipo de destino * . -
-Wswitch-default
: avisar cuando una instrucciónswitch
no tiene un caso pordefault
* . -
-Wswitch-enum
: avisar siempre que una instrucciónswitch
tenga un índice de tipo enumerado y carece de uncase
para uno o más de los códigos con nombre de esa enumeración * . -
-Wconversion
: advierte sobre las conversiones implícitas que pueden alterar un valor * . -
-Wunreachable-code
: avisa si el compilador detecta que el código nunca se ejecutará * .
Aquellos marcados * a veces dan demasiadas advertencias espurias, así que los uso según sea necesario.
Aquí hay una gran bandera que no se ha mencionado:
-Werror-implicit-function-declaration
Proporcione un error siempre que se use una función antes de declararla.
Bueno, -Wextra
debería ser estándar. -Werror
convierte las advertencias en errores (lo que puede ser muy molesto, especialmente si compila sin -Wno-unused-result
). -pedantic
en combinación con std=c89
le da advertencias adicionales si usa las características C99.
Pero eso es todo. No se puede sintonizar un compilador de C en algo más que guardar el tipo de letra C en sí mismo.
Encontré este hilo buscando una bandera para corregir un problema específico, no lo veo aquí, así que agregaré uno que me estaba golpeando en mi publicación :
La bandera de -Wformat=2
-Wformat
=> Verifique las llamadas aprintf
yscanf
, etc., para asegurarse de que los argumentos proporcionados tengan los tipos apropiados para la cadena de formato especificada ...
Y la parte realmente importante al respecto (de acuerdo con el manual de GCC ):
-Wformat
está incluido en-Wall
. Para un mayor control sobre algunos aspectos de la comprobación de formato, las opciones-Wformat-y2k
,-Wno-format-extra-args
,-Wno-format-zero-length
,-Wformat-nonliteral
-Wformat-security
,-Wformat-security
y-Wformat=2
están disponibles, pero no están incluidos en -Wall.
Entonces, solo porque lo tienes -Wall
no significa que lo tienes todo. ;)
Hay -Werror
, que trata todas las advertencias como errores y detiene la compilación. La página del manual de gcc
explica cada cambio de línea de comando para su compilador.
Me sorprende que nadie haya dicho esto todavía, la bandera más útil en lo que a mí respecta es la " -g
que coloca la información de depuración en el ejecutable para que pueda depurarla y pasar por la fuente (a menos que sea competente y lea assembly y como el comando stepi
) de un programa mientras se está ejecutando.
Mi archivo MAKE contiene típicamente
CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
...
g++ $(CFLAGS) -o junk $<
gcc $(CFLAGS) -o $@ $<
rm -f junk
Las más importantes de estas opciones se han discutido anteriormente, por lo que señalaré las dos características que aún no se han señalado:
Aunque estoy trabajando en una base de código que debe ser simple C para la portabilidad de alguna plataforma que todavía no tiene un compilador decente de C ++, realizo una compilación "extra" con el compilador de C ++ (además del compilador de C). Eso tiene 3 beneficios:
- el compilador de C ++ ocasionalmente me da mejores mensajes de advertencia que el compilador de C.
- El compilador C ++ acepta la opción -Weffc ++, que ocasionalmente me da algunos consejos útiles, que me perdería si solo lo compilé en C.
- Puedo mantener el código relativamente fácil de portar a C ++, evitando unas pocas condiciones de frontera donde el código simple C es un código inválido de C ++ (como la definición de una variable llamada "bool").
Sí, soy una Pollyanna desesperadamente optimista que sigue pensando que seguramente cualquier mes ahora una de las plataformas se declarará obsoleta o se obtendrá un compilador C ++ decente, y finalmente podremos cambiar a C ++. En mi opinión, es inevitable: la única pregunta es si eso sucede antes o después de que la administración finalmente les eche a todos un pony. :-)
No es realmente útil para detectar errores, pero la rara vez mencionada opción -masm=intel
hace que usar -S
para inspeccionar la salida del conjunto sea mucho, mucho más agradable.
La sintaxis de ensamblaje de AT & T me duele demasiado la cabeza.
No está realmente relacionado con C / C ++, pero de todos modos es útil:
@file
Coloque todos los indicadores buenos (que todos ha especificado) en un ''archivo'', y use este indicador de arriba para usar todos los indicadores en ese archivo juntos.
p.ej:
Archivo: compilerFlags
-Pared
-std = c99
-Wextra
Luego compila:
gcc yourSourceFile @compilerFlags
Si bien esta respuesta puede estar ligeramente fuera de tema y la pregunta es digna de +1, ya que
Estoy particularmente interesado en advertencias adicionales, y / o convirtiendo advertencias en errores en algunos casos para minimizar absolutamente cualquier desajuste de tipos accidentales.hay una herramienta que debe detectar TODOS los errores y posibles errores que pueden no ser obvios, hay una splint que en mi humilde opinión hace un trabajo mucho mejor para detectar errores en comparación con gcc o cualquier otro compilador para ese asunto. Esa es una herramienta valiosa para tener en su caja de herramientas.
La comprobación estática a través de una herramienta de tipo de pelusa, como la férula, debería haber sido parte de una cadena de herramientas de compilación.
Si necesita conocer los indicadores del preprocesador que están predefinidos por el compilador:
echo | gcc -E -dM -
Utilice siempre -O
o superior ( -O1
, -O2
, -Os
, etc.). En el nivel de optimización predeterminado, gcc utiliza la velocidad de compilación y no hace suficiente análisis para advertir acerca de cosas como variables unificadas.
Considere hacer -Werror
política de -Werror
, ya que las advertencias que no detienen la compilación tienden a ignorarse.
-Wall
prácticamente enciende las advertencias que muy probablemente sean errores.
Las advertencias incluidas en -Wextra
tienden a marcar código común y legítimo. Pueden ser útiles para revisiones de código (aunque los programas de estilo lint encuentran que muchas trampas son más flexibles), pero yo no los activaría para un desarrollo normal.
-Wfloat-equal
es una buena idea si los desarrolladores del proyecto no están familiarizados con el punto flotante, y una mala idea si lo son.
-Winit-self
es útil; Me pregunto por qué no está incluido en -Wuninitialized
.
-Wpointer-arith
es útil si tienes un código mayormente portable que no funciona con -pedantic
.
Varias de las opciones de generación de código -f
son interesantes:
La función
-ftrapv
hará que el programa aborte el desbordamiento de entero con signo (formalmente "comportamiento indefinido" en C).-fverbose-asm
es útil si está compilando con-S
para examinar el resultado del ensamblado, agrega algunos comentarios informativos.-finstrument-functions
agrega código para llamar a las funciones de creación de perfiles proporcionadas por el usuario en cada punto de entrada y salida de función.
-M*
familia de opciones.
Estos le permiten escribir archivos make que automáticamente descifren de qué archivos de cabecera deben depender sus archivos fuente c o c ++. GCC generará archivos make con esta información de dependencia, y luego los incluirá desde su archivo make primario.
Aquí hay un ejemplo de un archivo MAK extremadamente genérico que usa -MD y -MP que compilará un directorio lleno de archivos fuente y de encabezado de C ++, y descubrirá todas las dependencias automáticamente:
CPPFLAGS += -MD -MP
SRC = $(wildcard *.cpp)
my_executable: $(SRC:%.cpp=%.o)
g++ $(LDFLAGS) -o $@ $^
-include $(SRC:%.cpp=%.d)
Aquí hay una publicación de blog que lo analiza con más profundidad: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html
-Wfloat-equal
De: http://mces.blogspot.com/2005/07/char-const-argv.html
Una de las otras advertencias nuevas que me gusta es la -Wfloat-equal. Ese advierte siempre que tienes un número de coma flotante en condiciones de igualdad. ¡Eso es brillante! Si ha programado todos los gráficos de una computadora o (peor :) algoritmo de geometría computacional, sabrá que no hay dos flotadores que coincidan con la igualdad ...
-march=native
para producir código optimizado para la plataforma (= chip) en el que está compilando
-fmudflap : agrega comprobaciones de tiempo de ejecución a todas las operaciones de puntero arriesgadas para capturar UB. Esto efectivamente inmuniza su programa de nuevo desbordamiento de búfer y ayuda a atrapar todo tipo de punteros colgantes.
Aquí hay una demostración:
$ 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
-Wstrict-prototypes -Wmissing-prototypes
-save-temps
Esto deja atrás los resultados del preprocesador y el ensamblaje.
La fuente preprocesada es útil para depurar macros.
El ensamblado es útil para determinar qué optimizaciones entraron en vigor. Por ejemplo, es posible que desee verificar que GCC esté haciendo una optimización de la cola de llamadas en algunas funciones recursivas, ya que sin ella puede potencialmente desbordar la pila.
man gcc
El manual está lleno de banderas interesantes con buenas descripciones. Sin embargo, -Wall probablemente hará que gcc sea lo más detallado posible. Si desea datos más interesantes, debe echar un vistazo a valgrind u otra herramienta para verificar errores.