Полезные флаги GCC для C

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

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

23 ответов


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

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

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

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


вот мои:

  • -Wextra, -Wall: эфирное.
  • -Wfloat-equal: полезно, потому что обычно тестирование чисел с плавающей точкой на равенство-это плохо.
  • -Wundef: предупреждать, если неинициализированный идентификатор оценивается в случае*.
  • -Wswitch-enum: предупреждать, когда switch оператор имеет индекс перечисляемого типа и не имеет case для одного или нескольких именованных кодов этого перечисления*.
  • -Wconversion: предупреждение для неявных преобразований, которые могут изменить значение*.
  • -Wunreachable-code: предупредите, если компилятор обнаружит, что код никогда не будет выполнен*.

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


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

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

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

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

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

-Winit-self полезно; интересно, почему он не включен в -Wuninitialized.

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


-save-temps

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

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

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


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


-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

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

@file

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

например:

файл: compilerFlags

стена

- std=c99

-Wextra

затем скомпилировать :

gcc yourSourceFile @compilerFlags

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


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

echo | gcc -E -dM -

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

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


мой makefile обычно содержит

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

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

хотя я работаю над кодовой базой, которая должен быть простым C для переносимости на некоторую платформу, что еще не имеет приличного компилятора C++, я делаю" дополнительную " компиляцию с компилятором C++ (в дополнение к компилятору C). Что имеет 3 преимущества:

  1. компилятор C++ иногда дает мне лучшие предупреждающие сообщения, чем компилятор C.
  2. компилятор C++ принимает параметр-Weffc++, который иногда дает мне некоторые полезные советы, которые я пропустил бы, если бы я только скомпилировал его в простой C.
  3. я могу относительно легко переносить код на C++, избегая нескольких граничных условий, когда простой код C является недопустимым кодом C++ (например, определение переменной с именем "тип bool.)"

Да, я безнадежно оптимистичная Поллианна, которая продолжает думать, что конечно в любой месяц теперь, когда одна платформа будет объявлена устаревшей, или получит приличный компилятор C++, и мы сможем, наконец, переключиться на C++. На мой взгляд, это неизбежно - вопрос только в том, произойдет ли это до или после того, как руководство наконец выдаст каждому пони. :-)


-Wstrict-prototypes -Wmissing-prototypes

вот отличный флаг, который не был упомянут:

-Werror-implicit-function-declaration

дайте ошибку всякий раз, когда функция используется перед объявлением.


man gcc

руководство полно интересных флагов с хорошими описаниями. Тем не менее, - Wall, вероятно, сделает gcc максимально подробным. Если вам нужны более интересные данные, вы должны взглянуть на valgrind или какой-либо другой инструмент для проверки ошибок.


Ну -Wextra должно быть нормой. -Werror превращает предупреждения в ошибки (которые могут быть очень раздражает, особенно если вы компилируете без -Wno-unused-result). -pedantic в сочетании с std=c89 дает вам дополнительные предупреждения, если вы используете стандарте C99 функции.

но это все. Вы не можете настроить компилятор C на что-то большее, чем сохранение типа, чем сам C.


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


-M* семейные варианты.

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

вот пример чрезвычайно общего файла makefile с использованием -MD и-MP, который будет компилировать каталог, полный исходных файлов и заголовков C++, и выяснить все зависимости автоматически:

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

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

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

вот сообщение в блоге, которое обсуждает его более подробно: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html


-Wfloat-equal

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

одно из других новых предупреждений, которое мне нравится,- wfloat-equal. Это предупреждает, когда у вас [есть] число с плавающей запятой в условии равенства. Это Брилиант! Если вы запрограммировали компьютерную графику или (хуже:) алгоритм вычислительной геометрии, вы знаете, что никакие два поплавка никогда не совпадают с равенством...


я нашел этот поток, ищущий флаг, чтобы исправить конкретную проблему, я не вижу его здесь, поэтому я добавлю тот, который просто ставил меня в тупик мой пост:

на -Wformat=2 флаг

-Wformat => проверить звонки printf и scanf, etc., чтобы убедиться, что предоставленные аргументы имеют типы, соответствующие указанной строке формата...

и очень важная часть об этом (согласно GCC руководство):

-Wformat входит в -Wall. Для большего контроля над некоторыми аспектами проверки формата, опции -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security и -Wformat=2 доступны, но не включены в стену.`

Итак, только потому, что у вас есть -Wall не значит, что у вас есть все это. ;)


Я иногда использую -s для гораздо меньшего исполняемого файла:

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

источник:http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options


хотя этот ответ может быть немного не по теме, и вопрос стоит +1 от меня, так как

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

статическая проверка с помощью инструмента типа lint, такого как splint, должна была быть частью цепочки инструментов компилятора.


меня особенно интересуют любые дополнительные предупреждения,

кроме -Wall, the -W или (-W работает со старыми версиями gcc, а также более новыми; более поздние версии поддерживают альтернативное имя -Wextra, что означает то же самое, но более описательно) включает различные дополнительные предупреждения.

есть также еще больше предупреждений, которые не включены ни одним из них, как правило, для вещей это более сомнительно плохо. Набор доступных опций зависит от используемой версии gcc-consult man gcc или info gcc для деталей, или см. документации для конкретной версии gcc, которая вас интересует. И -pedantic выдает все предупреждения, требуемые конкретным используемым стандартом (который зависит от других параметров, таких как -std=xxx или -ansi) и жалуется на использование расширений gcc.

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

-Werror превращает все предупреждения как ошибки. Я не думаю, что gcc позволяет вам делать это выборочно для конкретных предупреждений.

вы, вероятно, обнаружите, что вы должны быть избирательными о том, какие предупреждения включены на основе каждого проекта (особенно если вы используете -Werror), поскольку заголовочные файлы из внешних библиотек могут отключать некоторые из них. (-pedantic в частности, как правило быть бесполезным в этом отношении, по моему опыту.)


  • -Wmissing-prototypes: если глобальная функция определена без предыдущего объявления прототипа.
  • -Wformat-security: предупреждает об использовании функций формата, представляющих возможные проблемы безопасности. В настоящее время это предупреждает о звонках printf и scanf функции, где строка формата не является строковым литералом и нет аргументов формата