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

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

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

Ответы

Ответ 1

Интересны некоторые из вариантов генерации кода -f:

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

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

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

Ответ 2

Вот мои:

  • -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: предупреждать, что компилятор обнаруживает, что этот код никогда не будет выполнен *.

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

Ответ 3

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

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

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

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

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

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

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

Ответ 4

-save-temps

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

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

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

Ответ 5

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

Ответ 6

-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

Ответ 7

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

@file

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

например:

Файл: compilerFlags

-Wall

-std = C99

-Wextra

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

gcc yourSourceFile @compilerFlags

Ответ 8

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

Ответ 9

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

echo | gcc -E -dM -

Ответ 10

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

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

Ответ 11

Мой файл makefile обычно содержит

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

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

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

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

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

Ответ 12

-Wstrict-prototypes -Wmissing-prototypes

Ответ 13

Здесь отличный флаг, который не упоминался:

-Werror-implicit-function-declaration

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

Ответ 14

man gcc

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

Ответ 15

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

Ответ 16

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

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

Ответ 17

-M* семейство опций.

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

Вот пример чрезвычайно универсального make файла, использующего -M D и -M P, который скомпилирует каталог, полный исходных и заголовочных файлов c++, и автоматически определит все зависимости:

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

my_executable: $(SRC:%.cpp=%.o)                                                        
        g++ $(LDFLAGS) -o [email protected] $^                                               

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

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

Ответ 18

-Wfloat-equal

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

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

Ответ 19

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

Флаг -Wformat=2

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

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

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

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

Ответ 21

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

меня особенно интересуют любые дополнительные предупреждения и/или превращают предупреждения в ошибки в некоторых случаях абсолютно минимизировать любые несоответствия случайных типов.
есть инструмент, который должен вылавливать ВСЕ ошибки и возможные ошибки, которые могут быть не очевидны, splint, который ИМХО лучше справляется с поиском ошибок по сравнению с gcc или любым другим компилятором. Это достойный инструмент для вашего инструментального сундука.

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

Ответ 22

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

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

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

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

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

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

Ответ 23

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

Ответ 24

  • -Werror=return-type: принудительная ошибка, когда функция не возвращает в gcc. Это /we4716 в Visual Studio.

  • -Werror=implicit-function-declaration: принудительная ошибка при использовании функции без определения/не включения. Это /we4013 в Visual Studio.

  • -Werror=incompatible-pointer-types: Enfore ошибка, когда тип указателя не соответствует ожидаемому типу указателя. Это /we4133 в Visual Studio.

На самом деле, я хотел бы сохранить свой C-код кроссплатформенным, и я использую CMake, и я помещаю предоставленные cflags в CMakeLists.txt, например:

if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4013 /we4133 /we4716")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Werror=return-type")
endif()