Вне установки -Wall
, и установка -std=XXX
, что другие действительно полезные, но менее известные флаги компилятора там для использования в C?
Я особенно интересуюсь любыми дополнительными предупреждениями, и/или и превращающими предупреждениями в ошибки в некоторых случаях для абсолютного уменьшения любых случайных несоответствий типов.
Интересны несколько вариантов генерации кода -f
:
Функция -ftrapv
заставит программу прерваться при переполнении целого числа со знаком. (формально «неопределенное поведение» в C).
-fverbose-asm
полезен, если вы компилируете с помощью -S
для проверки вывода сборки - он добавляет некоторые информативные комментарии.
-finstrument-functions
добавляет код для вызова пользовательских функций профилирования в каждой точке входа и выхода функции.
Меня особенно интересуют любые дополнительные предупреждения,
В дополнение к -Wall
, -W
или -Wextra Параметр
( -W
работает как со старыми версиями gcc, так и с более новыми; более свежие версии поддерживают альтернативное имя -Wextra
, что означает то же самое, но больше описательный) включает различные дополнительные предупреждения.
Есть также еще больше предупреждений, которые не активируются ни одним из них, как правило, для более сомнительно плохих вещей. Набор доступных параметров зависит от того, какую версию gcc вы используете - обратитесь к man gcc
или info gcc
, чтобы узнать подробности, или см. онлайн-документацию для получения более подробной информации. Версия gcc, которая вас интересует. А -pedantic
выдает все предупреждения, требуемые конкретным используемым стандартом (что зависит от других параметров, таких как -std = xxx
или - ansi
) и жалуется на использование расширений gcc.
и / или превращение предупреждений в ошибки в некоторых случаях, чтобы полностью свести к минимуму любой случайный тип несоответствия.
-Werror
превращает все предупреждения в ошибки. Однако я не думаю, что gcc позволяет делать это выборочно для определенных предупреждений.
Вы, вероятно, обнаружите, что вам нужно выбирать, какие предупреждения включаются для каждого проекта (особенно, если вы используете -Werror
), поскольку файлы заголовков из внешних библиотек могут отключать некоторые из их. ( -педантический
, в частности, имеет тенденцию быть бесполезным в этом отношении, по моему опыту.)
Существует -Werror
, которая обрабатывает все предупреждения как ошибки и останавливает компиляцию. На странице руководства gcc
описаны все параметры командной строки для вашего компилятора.
man gcc
В руководстве много интересных флагов с хорошими описаниями. Однако -Wall, вероятно, сделает gcc максимально подробным. Если вам нужны более интересные данные, вам следует взглянуть на valgrind или какой-либо другой инструмент для проверки ошибок.
-march = native
для создания оптимизированного кода для платформы (= чипа), на которой вы компилируете
Я удивлен, что никто этого еще не сказал - на мой взгляд, наиболее полезный флаг - -g
, который помещает отладочную информацию в исполняемый файл, чтобы вы могли отлаживать его и переходить по исходному тексту (если вы не умеете читать сборку и не любите команду stepi
) программы во время ее выполнения.
Иногда я использую -s
для гораздо меньшего исполняемого файла:
-s
Remove all symbol table and relocation information from the executable.
Источник: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
Если вам нужно знать флаги препроцессора, которые предопределены компилятором:
echo | gcc -E -dM -
Ну, -Wextra
тоже должна быть стандартной. -Werror
превращает предупреждения в ошибки (что может быть очень раздражающим, особенно если вы компилируете без -Wno-unused-result
). -pedantic
в сочетании с std = c89
выдает дополнительные предупреждения, если вы используете функции C99.
Но это все. Вы не можете настроить компилятор C на что-то более сохраняющее тип, чем сам C.
Вот мои:
-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
case*. -Wswitch-enum
: предупреждать всякий раз, когда оператор switch
имеет индекс перечислимого типа и не имеет case
для одного или более именованных кодов этого перечисления*. -Wconversion
: предупреждение для неявных преобразований, которые могут изменить значение*. -Wunreachable-code
: предупреждение, если компилятор обнаруживает, что код никогда не будет выполнен*. Те, что помечены *, иногда выдают слишком много ложных предупреждений, поэтому я использую их по мере необходимости.
Всегда используйте -O
или выше (-O1
, -O2
, -Os
и т.д.). При уровне оптимизации по умолчанию gcc стремится к скорости компиляции и не делает достаточного анализа, чтобы предупредить о таких вещах, как унифицированные переменные.
Рассмотрите возможность сделать -Werror
политикой, поскольку предупреждения, которые не останавливают компиляцию, обычно игнорируются.
-Wall
в основном включает предупреждения, которые с большой вероятностью могут оказаться ошибками.
Предупреждения, включенные в -Wextra
, обычно отмечают обычный, легитимный код. Они могут быть полезны при обзоре кода (хотя программы в стиле lint находят гораздо больше подводных камней, они более гибкие), но я бы не стал включать их при обычной разработке.
-Wfloat-equal
- хорошая идея, если разработчики проекта незнакомы с плавающей запятой, и плохая, если знакомы.
-Winit-self
полезен; интересно, почему он не включен в -Wuninitialized
.
-Wpointer-arith
полезен, если у вас есть в основном переносимый код, который не работает с -pedantic
.
-Wfloat-equal
From: http://mces.blogspot.com/2005/07/char-const-argv.html
One of the other new warnings that I like is the -Wfloat-equal. That one warns whenever you [have] a floating-point number in an equality condition. That's briliant! If you have every programmed a computer graphics or (worse:) computational geometry algorithm, you know that no two floats ever match with equality...
Это не очень полезно для обнаружения ошибок, но редко упоминаемая опция -masm = intel
делает использование -S
для проверки вывода сборки намного лучше.
Синтаксис ассемблера AT&T слишком разбивает мне голову.
-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
Хотя этот ответ может быть немного не по теме, и вопрос стоит от меня +1, так как
меня особенно интересуют любые дополнительные предупреждения и / или предупреждения о включении в ошибки в некоторых случаях, чтобы полностью свести к минимуму любые случайные несоответствия типов.есть инструмент, который должен вылавливать ВСЕ ошибки и потенциальные ошибки, которые могут быть неочевидными, есть splint , который, ИМХО, лучше справляется с поиском ошибок по сравнению с gcc или любой другой компилятор в этом отношении. Это достойный инструмент, который стоит иметь в вашем ящике с инструментами.
Статическая проверка с помощью инструмента типа lint, такого как splint, должна была быть частью инструментальной цепочки компилятора.
-save-temps
При этом остаются результаты работы препроцессора и ассемблера.
Препроцессированный исходный текст полезен для отладки макросов.
Сборка полезна для определения того, какие оптимизации были применены. Например, вы можете проверить, что GCC выполняет оптимизацию хвостовых вызовов для некоторых рекурсивных функций, поскольку без этого вы можете потенциально переполнить стек.
Мой make-файл обычно содержит
CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
...
g++ $(CFLAGS) -o junk $<
gcc $(CFLAGS) -o $@ $<
rm -f junk
Наиболее важные из этих параметров обсуждались ранее, поэтому я выделю две функции, на которые еще не указывалось:
Хотя я работаю над кодовой базой что требует, чтобы был простым C для переносимости на некоторую платформу, которая по-прежнему не имеет достойного компилятора C ++, я делаю «дополнительную» компиляцию с компилятором C ++ (в дополнение к компилятору C) . У этого есть 3 преимущества:
Да, я безнадежно оптимистичная Поллианна, которая все время думает, что наверняка в любой момент, когда одна платформа будет объявлена устаревшей или получит достойный компилятор C ++, и мы наконец сможем перейти на C ++. На мой взгляд, это неизбежно - вопрос только в том, произойдет ли это до или после того, как руководство наконец выдаст всем пони. : -)
Вот отличный флаг, о котором не упоминалось:
-Werror-implicit-function-declaration
Выдавать ошибку всякий раз, когда функция используется перед ее объявлением.