Полезные флаги GCC для C - PullRequest
152 голосов
/ 31 июля 2010

Помимо настройки -Wall и настройки -std=XXX, какие еще действительно полезные, но менее известные флаги компилятора существуют для использования в C?

Меня особенно интересуют любые дополнительные предупреждения и /или и превращение предупреждений в ошибки в некоторых случаях, чтобы свести к минимуму случайные несоответствия типов.

Ответы [ 24 ]

133 голосов
/ 31 июля 2010

Вот мои:

  • -Wextra, -Wall: необходимо.
  • -Wfloat-equal: полезно, потому что обычно проверка чисел с плавающей точкой на равенство плохая.
  • -Wundef: предупредить, если неинициализированный идентификатор оценивается в директиве #if.
  • -Wshadow: предупредить, когда локальная переменная затеняет другую локальную переменную, параметр или глобальную переменную или когда затенена встроенная функция.
  • -Wpointer-arith: предупредить, если что-то зависит от размера функции или void.
  • -Wcast-align: предупреждать всякий раз, когда указатель приведен так, что требуемое выравнивание цели увеличивается. Например, предупредите, если char * приведен к int * на машинах, где целые числа доступны только на двух- или четырехбайтовых границах.
  • -Wstrict-prototypes: предупредить, если функция объявлена ​​или определена без указания типов аргументов.
  • -Wstrict-overflow=5: предупреждает о случаях, когда компилятор оптимизирует, исходя из предположения, что переполнение со знаком не происходит. (Значение 5 может быть слишком строгим, см. Страницу руководства.)
  • -Wwrite-strings: присвойте строковым константам тип const char[ length ], чтобы при копировании адреса единицы в не const char * указатель получало предупреждение.
  • -Waggregate-return: предупредить, если определены или вызваны какие-либо функции, которые возвращают структуры или объединения.
  • -Wcast-qual: предупреждать, когда указатель приведен для удаления спецификатора типа из целевого типа *.
  • -Wswitch-default: предупреждать, если в выражении switch нет default регистра *.
  • -Wswitch-enum: предупреждать, когда у оператора switch есть индекс перечислимого типа и отсутствует case для одного или нескольких именованных кодов этого перечисления *.
  • -Wconversion: предупреждение о неявных преобразованиях, которые могут изменить значение *.
  • -Wunreachable-code: предупредить, если компилятор обнаружит, что код никогда не будет выполнен *.

Отмеченные * иногда дают слишком много ложных предупреждений, поэтому я использую их по мере необходимости.

63 голосов
/ 31 июля 2010

Несколько вариантов генерации кода -f интересны:

  • Функция -ftrapv приведет к прерыванию программы при целочисленном переполнении со знаком (формально "неопределенное поведение" в C).

  • -fverbose-asm полезно, если вы компилируете с -S для проверки вывода сборки - он добавляет несколько информативных комментариев.

  • -finstrument-functions добавляет код для вызова предоставленных пользователем функций профилирования в каждой точке входа и выхода функции.

50 голосов
/ 31 июля 2010

Всегда используйте -O или выше (-O1, -O2, -Os и т. Д.). На уровне оптимизации по умолчанию gcc использует скорость компиляции и не проводит достаточного анализа, чтобы предупредить о таких вещах, как унифицированные переменные.

Рассмотрите возможность принятия политики -Werror, поскольку предупреждения, которые не останавливают компиляцию, обычно игнорируются.

-Wall в значительной степени включает предупреждения, которые с большой вероятностью могут быть ошибками.

Предупреждения, включенные в -Wextra, имеют тенденцию помечать общий, допустимый код. Они могут быть полезны для обзоров кода (хотя программы в стиле lint находят гораздо больше ловушек более гибкими), но я не включил бы их для нормальной разработки.

-Wfloat-equal - хорошая идея, если разработчики проекта не знакомы с плавающей запятой, и плохая идея, если они есть.

-Winit-self полезно; Интересно, почему это не входит в -Wuninitialized.

-Wpointer-arith полезно, если у вас есть в основном переносимый код, который не работает с -pedantic.

37 голосов
/ 03 августа 2010
-save-temps

Это оставляет позади результаты препроцессора и сборки.

Предварительно обработанный источник полезен для отладки макросов.

Сборка полезна для определения того, какие оптимизации вступили в силу,Например, вы можете убедиться, что GCC выполняет оптимизацию хвостового вызова для некоторых рекурсивных функций, так как без этого вы можете потенциально переполнить стек.

35 голосов
/ 31 июля 2010

Я удивлен, что никто еще не сказал это - самый полезный флаг, насколько мне известно, это -g, который помещает отладочную информацию в исполняемый файл, так что вы можете отлаживать ее и проходить по источнику (если вы не ' опытный и читающий сборку и подобный команде stepi) программы во время ее выполнения.

35 голосов
/ 03 августа 2010

-fmudflap - добавляет проверки во время выполнения ко всем операциям с рискованным указателем, чтобы поймать UB.Это эффективно предотвращает переполнение буфера в вашей программе и помогает отлавливать все виды висячих указателей.

Вот демоверсия:

$ 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
19 голосов
/ 15 июля 2013

Не совсем связано с C / C ++, но в любом случае полезно:

@file

Поместите все вышеупомянутые хорошие флаги (которые вы все указали) в «файл» и используйте этот выше флаг, чтобы использовать все флаги в этом файле вместе.

например:

Файл: compilerFlags

-Wall

-std = c99

-Wextra

Затем скомпилируйте:

gcc yourSourceFile @compilerFlags
15 голосов
/ 31 июля 2010

-march=native для создания оптимизированного кода для платформы (= чип), на которой вы компилируете

13 голосов
/ 04 августа 2010

Это не очень полезно для обнаружения ошибок, но редко упоминаемая опция -masm=intel заставляет использовать -S для проверки выходных данных сборки намного, намного приятнее.

Синтаксис сборки AT & T слишком сильно ранит мою голову.

13 голосов
/ 31 июля 2010

Если вам нужно знать флаги препроцессора, которые предопределены компилятором:

echo | gcc -E -dM -
...