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

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

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

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

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

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

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

    Вот мои:

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

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

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

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

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

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

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

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

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

     -save-temps 

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

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

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

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

    -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

    -Wall

    -std = C99

    -Wextra

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

     gcc yourSourceFile @compilerFlags 

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

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

     echo | gcc -E -dM - 

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

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

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

      CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb ... g++ $(CFLAGS) -o junk $< gcc $(CFLAGS) -o [email protected] $< 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 , который обрабатывает все предупреждения как ошибки и останавливает компиляцию. На странице руководства gcc описывается каждый ключ командной строки для вашего компилятора.

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

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

    Вот пример чрезвычайно общего make-файла с использованием -MD и -MP, который будет скомпилировать каталог, полный исходных и заголовочных файлов 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/automatically_generate_makefile_dependencies.html

    -Wfloat-equal

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

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

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

    Флаг -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 это не значит, что у вас есть все. 😉

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

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

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

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

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

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

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

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

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

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

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

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

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

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