Полезные флаги GCC для C
Помимо настройки -Wall
и установки -std=XXX
, какие другие действительно полезные, но менее известные флаги компилятора существуют для использования в C?
Меня особенно интересуют любые дополнительные предупреждения и / или, и в некоторых случаях превращая предупреждения в ошибки, чтобы полностью свести к минимуму любые несоответствия случайного типа.
- Как увидеть, какие флаги -march = native будут активированы?
- Является ли уровень оптимизации -О3 опасным в g ++?
- Как установить флаги компилятора CUDA в Visual Studio 2010?
- Разница между -pthread и -lpthread при компиляции
- Как отключить неиспользуемые предупреждения переменных, выходящие из gcc в стороннем коде, который я не хочу редактировать?
Некоторые из вариантов генерации кода -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
: дать строковые константы typeconst char[
length]
чтобы копирование адреса одного в указатель nonconst 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 преимущества:
- компилятор C ++ иногда дает мне лучшие предупреждающие сообщения, чем компилятор C.
- Компилятор C ++ принимает параметр -Weffc ++, который иногда дает мне несколько полезных советов, которые я бы пропустил, если бы я только скомпилировал его на простом C.
- Я могу сохранить код относительно легко переносить на 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
где строка формата не является строковым литералом, и нет аргументов формата