Я просмотрел и нашел минимальный набор включений, который должен получать максимальный уровень предупреждений. Затем я удалил из этого списка набор предупреждений, которые, как мне кажется, на самом деле не указывают на то, что происходит что-то плохое, или имеют слишком много ложных срабатываний для использования в реальной сборке. Я прокомментировал, почему все исключенные мной были исключены. Это мой последний набор рекомендуемых предупреждений:
Я включаю, -Wno-unused
потому что у меня часто есть переменные, которые я знаю, что буду использовать позже, но для которых еще нет написанных функций. Удаление предупреждений об этом позволяет мне писать в своем предпочтительном стиле, иногда откладывая реализацию вещей. Полезно выключать это время от времени, чтобы убедиться, что ничего не проскочило через щели.
-Wdisabled-optimization
похоже на сильную настройку предпочтений пользователя. Я только что добавил это в свою сборку (только для оптимизированных сборок по понятным причинам), и ничего не получилось, так что это не кажется особо разговорчивым предупреждением, по крайней мере, для того, как я кодирую. Я включаю его (хотя код, который вызывает это предупреждение, не обязательно ошибочен), потому что я верю, что могу работать с моими инструментами, а не против них. Если gcc сообщает мне, что он не может оптимизировать код в соответствии с тем, как я его написал, то мне следует подумать о его переписывании. Я подозреваю, что код, который запускает это предупреждение, в любом случае может выиграть от большей модульности, поэтому, хотя код не является технически неправильным (вероятно), стилистически скорее всего так.
-Wfloat-equal
предупреждает о безопасном сравнении равенства (в частности, сравнение с невычисленным значением -1). Пример в моем коде, где я использую это, заключается в том, что у меня есть вектор с плавающей запятой. Я просматриваю этот вектор, и есть некоторые элементы, которые я пока не могу оценить, какими они должны быть, поэтому я установил для них -1.0f (поскольку моя проблема использует только положительные числа, -1 находится вне области). Позже я просматриваю и обновляю значения -1.0f. Его нелегко применить к другому методу работы. Я подозреваю, что у большинства людей этой проблемы нет, и сравнение точного числа с плавающей запятой, вероятно, является ошибкой, поэтому я включаю его в список по умолчанию.
-Wold-style-cast
имеет много ложных срабатываний в коде библиотеки, который я использую. В частности, семейство функций htonl, используемых в сети, а также реализация шифрования Rijndael (AES), которую я использую, имеют приведения в старом стиле, о которых меня предупреждают. Я намерен заменить оба из них, но я не уверен, есть ли в моем коде что-то еще, на что он будет жаловаться. Однако большинству пользователей, вероятно, следует включить его по умолчанию.
-Wsign-conversion
был трудным (и почти не попал в список). Включение его в моем коде генерировало огромное количество предупреждений (более 100). Почти все они были невиновны. Тем не менее, я старался использовать целые числа со знаком там, где я не был уверен, хотя для моей конкретной проблемной области я обычно получал небольшое повышение эффективности с использованием значений без знака из-за большого количества целочисленных делений, которые я делаю. Я пожертвовал этой эффективностью, потому что был обеспокоен случайным преобразованием целого числа со знаком в беззнаковое с последующим делением (что небезопасно, в отличие от сложения, вычитания и умножения). Включение этого предупреждения позволило мне безопасно изменить большинство моих переменных на беззнаковые типы и добавить несколько приведений в некоторых других местах. В настоящее время это немного сложно использовать, потому что предупреждение не так умно. Например, если вы сделаетеunsigned short + (integral
constant expression)
, этот результат неявно повышается до int. Затем он предупреждает о потенциальной проблеме со знаком, если вы присвоите это значение
unsigned
или unsigned short
, даже если это безопасно. Это определенно самое необязательное предупреждение почти для всех пользователей.
-Wsign-promo
: см -Wsign-conversion
.
-Wswitch-default
кажется бессмысленным (вам не всегда нужен вариант по умолчанию, если вы явно перечислили все возможности). Однако включение этого предупреждения может привести к тому, что это, вероятно, хорошая идея. В случаях, когда вы явно хотите игнорировать все, кроме перечисленных возможностей (но возможны другие числа), введитеdefault: break;
чтобы сделать это явным. Если вы явно перечисляете все возможности, то включение этого предупреждения поможет убедиться, что вы указали что-то вроде assert (false), чтобы убедиться, что вы действительно охватили все возможные варианты. Это позволяет вам четко указать, в чем состоит ваша проблема, и программно обеспечивает это. Однако вам нужно быть осторожным, просто вставляя везде assert (false). Это лучше, чем ничего не делать со случаем по умолчанию, но, как обычно с assert, он не будет работать в сборках выпуска. Другими словами, вы не можете полагаться на него для проверки чисел, которые вы получаете, скажем, от сетевого подключения или базы данных, над которой у вас нет абсолютного контроля. Исключения или досрочное возвращение - лучший способ справиться с этим (но все же требуется, чтобы у вас был случай по умолчанию!).
-Werror
для меня важен. При компиляции большого количества кода в многопоточной сборке с несколькими целями предупреждение легко пропустить. Превращение предупреждений в ошибки гарантирует, что я их замечу.
Затем есть набор предупреждений, которые не включены в приведенный выше список, потому что я не нашел их полезными. Это предупреждения и мои комментарии о том, почему я не включаю их в список по умолчанию:
-Wabi
не нужен, потому что я не комбинирую двоичные файлы из разных компиляторов. Я все равно пытался скомпилировать с ним, но он не сработал, поэтому он не кажется излишне многословным.
-Waggregate-return
это не то, что я считаю ошибкой. Например, он срабатывает при использовании цикла for на основе диапазона для вектора классов. Оптимизация возвращаемого значения должна позаботиться о любых негативных последствиях этого.
-Wconversion
триггеры для этого кода: short n = 0; n += 2;
неявное преобразование в int вызывает предупреждение, когда оно затем преобразуется обратно в свой целевой тип.
-Weffc++
включает предупреждение, если все элементы данных не инициализированы в списке инициализаторов. Во многих случаях я намеренно не делаю этого, поэтому набор предупреждений слишком загроможден, чтобы быть полезным. Тем не менее, полезно время от времени включать и сканировать другие предупреждения (например, не виртуальные деструкторы базовых классов). Это было бы более полезно в качестве набора предупреждений (например, -Wall
), а не отдельного предупреждения.
-Winline
отсутствует, потому что я не использую ключевое слово inline в целях оптимизации, просто для определения функций, встроенных в заголовки. Меня не волнует, действительно ли оптимизатор встраивает его. Это предупреждение также указывает на то, что не может встроить функцию, объявленную в теле класса (например, пустой виртуальный деструктор).
-Winvalid-pch
отсутствует, потому что я не использую предварительно скомпилированные заголовки.
-Wmissing-format-attribute
не используется, потому что я не использую расширения GNU. То же самое для -Wsuggest-attribute
и некоторых других
Потенциально примечателен своим отсутствием -Wno-long-long
, в котором я не нуждаюсь. Я компилирую -std=c++0x
( -std=c++11
в GCC 4.7), который включает long long
целочисленные типы. Те, кто застрял на C ++ 98 / C ++ 03, могут подумать о добавлении этого исключения из списка предупреждений.
-Wnormalized=nfc
уже является вариантом по умолчанию и выглядит лучшим.
-Wpadded
время от времени включается для оптимизации компоновки классов, но не остается включенным, потому что не все классы имеют достаточно элементов для удаления отступов в конце. Теоретически я мог бы получить несколько дополнительных переменных «бесплатно», но это не стоит дополнительных усилий по их поддержанию (если размер моего класса изменится, будет нелегко удалить эти ранее свободные переменные).
-Wstack-protector
не используется, потому что я не использую -fstack-protector
-Wstrict-aliasing=3
включен -Wall
и является наиболее точным, но похоже, что уровни 1 и 2 дают больше предупреждений. Теоретически более низкий уровень является «более сильным» предупреждением, но это происходит за счет большего количества ложных срабатываний. Мой собственный тестовый код аккуратно скомпилирован на всех трех уровнях.
-Wswitch-enum
поведение не то, что я хочу. Я не хочу явно обрабатывать каждый оператор switch. Было бы полезно, если бы в языке был какой-то механизм для активации этого в определенных операторах switch (чтобы гарантировать, что будущие изменения в перечислении обрабатываются везде, где они должны быть), но это излишне для параметра «все или ничего».
-Wunsafe-loop-optimizations
вызывает слишком много ложных предупреждений. Может быть полезно применять его периодически и вручную проверять результаты. Например, это предупреждение было сгенерировано в моем коде, когда я перебирал все элементы вектора, чтобы применить к ним набор функций (используя цикл for на основе диапазона). Это также предупреждение для конструктора константного массива const std :: string (где это не цикл в пользовательском коде).
-Wzero-as-null-pointer-constant
и -Wuseless-cast
являются предупреждениями только для GCC-4.7, которые я добавлю при переходе на GCC 4.7.
Я подал несколько отчетов об ошибках / запросов на улучшение в gcc в результате некоторых из этих исследований, поэтому, надеюсь, я смогу в конечном итоге добавить больше предупреждений из списка «не включать» в список «включить» , Этот список включает все предупреждения, упомянутые в этой теме (плюс, я думаю, несколько дополнительных). Многие из предупреждений, явно не упомянутых в этом сообщении, включены как часть другого предупреждения, о котором я упоминаю. Если кто-нибудь заметит какие-либо предупреждения, которые полностью исключены из этого сообщения, дайте мне знать.
-Wall
) является-Wbloody_everything
флаг :-)