Как программист C & Objective-C, я немного параноик с флагами предупреждения компилятора.
Я обычно пытаюсь найти полный список флагов предупреждений для используемого мной компилятора и включать большинство из них, если только у меня нет веской причины не включать его.
Лично я считаю, что это может улучшить навыки кодирования, а также потенциальную переносимость кода, предотвратить некоторые проблемы, поскольку заставляет вас быть в курсе всех мелких деталей, потенциальных проблем с реализацией и архитектурой и так далее ...
Это также, на мой взгляд, хороший инструмент для повседневного обучения, даже если вы опытный программист.
Что касается субъективной части этого вопроса, мне интересно услышать об этой теме других разработчиков (в основном C, Objective-C и C ++).
Вы действительно заботитесь о таких вещах, как педантичные предупреждения и т. Д.? И если да или нет, то почему?
Теперь о Objective-C, я недавно полностью переключился на набор инструментов LLVM (с Clang) вместо GCC.
В моем производственном коде я обычно устанавливаю эти флаги предупреждения (явно, даже если некоторые из них могут быть охвачены -Wall):
- -Wall
- -Wbad-функция-литой
- -Wcast выравнивания
- -Wconversion
- -Wdeclaration-после заявления
- -Wdeprecated-реализации
- -Wextra
- -Wfloat равных
- -Wformat = 2
- -Wformat-nonliteral
- -Wfour-символьная-константа
- -Wimplicit-атомно-свойства
- -Wmissing-распорки
- -Wmissing-декларации
- -Wmissing-полевые инициализаторы
- -Wmissing-формат-атрибут
- -Wmissing-noreturn
- -Wmissing-прототипы
- -Wnested-экстернов
- -Wnewline-ВФ
- -Wold стиль четкость
- -Woverlength-строки
- -Wparentheses
- -Wpointer-Arith
- -Wredundant-decls
- -Wreturn типа
- -Wsequence-точка
- -Wshadow
- -Wshorten-64-к-32
- -Wsign-сравнить
- -Wsign-преобразования
- -Wstrict-прототипы
- -Wstrict-селектор матча
- -Wswitch
- -Wswitch по умолчанию
- -Wswitch-перечисление
- -Wundeclared-селектор
- -Wuninitialized
- -Wunknown-псевдокомментарий
- -Wunreachable-код
- -Wunused-функция
- -Wunused метки
- -Wunused-параметр
- -Wunused значение
- -Wunused переменной
- -Wwrite-строки
Мне интересно услышать, что другие разработчики могут сказать по этому поводу.
Например, вы думаете, что я пропустил определенный флаг для Clang (Objective-C), и почему?
Или вы думаете, что конкретный флаг бесполезен (или вообще не нужен) и почему?
РЕДАКТИРОВАТЬ
Чтобы прояснить вопрос, обратите внимание, что -Wall
содержит только несколько основных предупреждений.
На самом деле они представляют собой гораздо больше предупреждающих флагов, не охватываемых -Wall
, отсюда и вопрос, и список, который я предоставляю.
источник
-Wwrite-strings
делает его компилятором языка очень похожим, но не совсем C. По этой причине я не использую эту опцию. Кроме тех, которые вы указываете, я использую-pedantic -Wstrict-overflow=5 -Winline -Wundef -Wcast-qual -Wlogical-op -Wstrict-aliasing=2
и-Wno-missing-braces -Wno-missing-field-initializers
для вполне разумного инициализатораstruct whatever obj = {0};
. Также я считаю, что это-Wconversion
дает больше «спама», чем полезных предупреждений :)Ответы:
Для контекста, я разработчик Clang, работающий в Google. В Google мы внедрили диагностику Clang (по существу) всем нашим разработчикам на C ++, и мы также рассматриваем предупреждения Clang как ошибки. Как разработчик Clang и один из крупнейших пользователей диагностики Clang, я постараюсь пролить свет на эти флаги и то, как их можно использовать. Обратите внимание, что все, что я описываю, в целом применимо к Clang, а не специфично для C, C ++ или Objective-C.
TL; DR версия: пожалуйста, используйте
-Wall
и-Werror
как минимум для любого нового кода, который вы разрабатываете. Мы (разработчики компилятора) добавляем сюда предупреждения по веским причинам: они находят ошибки. Если вы найдете предупреждение, которое ловит вас за ошибки, включите его. Попробуйте-Wextra
здесь кучу хороших кандидатов. Если один из них слишком шумный для вас, чтобы использовать его с выгодой, сообщите об ошибке . Если вы пишете код, который содержит «очевидную» ошибку, но компилятор не предупредил об этом, сообщите об ошибке.Теперь для длинной версии. Сначала немного информации о группах предупреждений. Существует много группировок предупреждений в Clang (и в ограниченной степени в GCC). Некоторые из них имеют отношение к этой дискуссии:
-Wall
: Это предупреждение о том , что разработчики имеют высокую уверенность в обеих их стоимости и низком уровне ложно-позитивности.-Wextra
Это предупреждения, которые считаются ценными и обоснованными (т. Е. Они не содержат ошибок), но могут иметь высокий уровень ложноположительных результатов или общие философские возражения.-Weverything
Это безумная группа, которая буквально включает каждое предупреждение в Clang. Не используйте это в своем коде. Он предназначен исключительно для разработчиков Clang или для изучения существующих предупреждений .Есть два основных критерия, упомянутых выше, которые определяют, куда направляются предупреждения в Clang, и давайте выясним, что они на самом деле означают. Первый - это потенциальная ценность конкретного появления предупреждения. Это ожидаемое преимущество для пользователя (разработчика), когда предупреждение срабатывает и правильно определяет проблему с кодом.
Вторым критерием является идея ложноположительных отчетов. Это ситуации, когда предупреждение срабатывает в коде, но потенциальная проблема, о которой идет речь, на самом деле не возникает из-за контекста или другого ограничения программы. Код, о котором предупреждено, на самом деле ведет себя правильно. Это особенно плохо, когда предупреждение никогда не предназначалось для запуска по этому шаблону кода. Напротив, недостаток в реализации предупреждения вызывает его срабатывание.
Для предупреждений Clang это значение должно быть с точки зрения правильности , а не с точки зрения стиля, вкуса или соглашений о кодировании. Это ограничивает набор доступных предупреждений, исключая часто запрашиваемые предупреждения, такие как предупреждение, всякий раз, когда
{}
s не используются в телеif
оператора. Clang также очень нетерпим к ложным срабатываниям . В отличие от большинства других компиляторов, он будет использовать невероятное разнообразие источников информации для сокращения ложных срабатываний, включая точное написание конструкции, наличие или отсутствие дополнительных '()', приведений или даже макросов препроцессора!Теперь давайте возьмем несколько реальных примеров предупреждений от Clang и посмотрим, как они классифицируются. Во-первых, предупреждение по умолчанию:
Здесь не требуется флаг, чтобы получить это предупреждение. Обоснование состоит в том, что этот код никогда не является действительно правильным, давая высокое значение предупреждения , и предупреждение срабатывает только на коде, который Clang может доказать, попадает в этот сегмент, давая ему нулевой уровень ложных срабатываний .
Clang требует
-Wall
флаг для этого предупреждения. Причина в том, что существует нетривиальный объем кода, который использовал (хорошо или плохо) шаблон кода, о котором мы предупреждаем, чтобы преднамеренно создать неинициализированное значение. С философской точки зрения, я не вижу в этом смысла, но многие другие не согласны, и реальность этого разногласия заключается в том, что движет предупреждением под-Wall
флагом. Он по-прежнему имеет очень высокое значение и очень низкий уровень ложноположительных результатов , но на некоторых кодовых базах он не является стартовым.Это предупреждение требует
-Wextra
флажка. Причина в том, что существуют очень большие кодовые базы, в которых несоответствующий знак сравнений встречается крайне часто. Хотя это предупреждение обнаруживает некоторые ошибки, вероятность того, что код будет ошибкой, когда пользователь пишет, в среднем достаточно низкая. Результатом является чрезвычайно высокий уровень ложноположительных результатов . Тем не менее, когда в программе есть ошибка из-за странных правил продвижения, часто очень трудно сделать это предупреждение, когда она отмечает ошибку , имеющую относительно высокое значение . Как следствие, Clang предоставляет это и выставляет это под флагом.Как правило, предупреждения не живут долго вне
-Wextra
флага. Clang очень старается не реализовывать предупреждения, которые не видят регулярного использования и тестирования. Дополнительные предупреждения, включенные-Weverything
обычно, являются предупреждениями при активной разработке или с активными ошибками. Либо они будут исправлены и помещены под соответствующие флаги, либо они должны быть удалены.Теперь, когда у нас есть понимание того, как эти вещи работают с Clang, давайте попробуем вернуться к первоначальному вопросу: какие предупреждения вы должны включить для своего развития? Ответ, к сожалению, зависит от этого. Примите во внимание следующие вопросы, чтобы определить, какие предупреждения лучше всего подходят для вашей ситуации.
Прежде всего, если вы не контролируете код, не пытайтесь включить туда дополнительные предупреждения. Будьте готовы выключить некоторые. В мире много плохого кода, и вы не сможете исправить все это. Все в порядке. Старайтесь найти способ сосредоточить свои усилия на коде, которым вы управляете.
Затем выясните, что вы хотите из своих предупреждений. Это разные для разных людей. Clang попытается предупредить без каких-либо опций о вопиющих ошибках или шаблонах кода, для которых у нас есть давний исторический прецедент, указывающий, что уровень ошибок чрезвычайно высок. Благодаря этому
-Wall
вы получите гораздо более агрессивный набор предупреждений, направленных на выявление наиболее распространенных ошибок, которые разработчики Clang наблюдали в коде C ++. Но с обоими из них уровень ложноположительных результатов должен оставаться довольно низким.Наконец, если вы абсолютно готовы замолчать * ложноположительные * на каждом шагу, сделайте это
-Wextra
. Сообщайте об ошибках, если вы замечаете предупреждения, которые содержат много реальных ошибок, но имеют ложные или бессмысленные ложные срабатывания. Мы постоянно работаем , чтобы найти способы , чтобы принести больше и больше ошибок ознакомительной логики представить в-Wextra
в-Wall
где мы можем избежать ложных срабатываний.Многие найдут, что ни один из этих вариантов не подходит именно им. В Google мы отключили некоторые предупреждения
-Wall
из-за большого количества существующего кода, который нарушил предупреждение. Мы также включили некоторые предупреждения явно, хотя они не включены-Wall
, потому что они имеют для нас особенно высокую ценность. Ваш пробег будет варьироваться, но, вероятно, будет меняться аналогичным образом. Часто бывает гораздо лучше включить несколько ключевых предупреждений, а не все-Wextra
.Я бы посоветовал всем включить
-Wall
любой не устаревший код. Для нового кода предупреждения здесь почти всегда полезны и действительно улучшают опыт разработки кода. И наоборот, я бы посоветовал всем не включать флаги за пределами-Wextra
. Если Вы нашли предупреждение Clang , что-Wextra
не включает в себя , но который оказывается совсем ценным для вас, просто файл ошибки , и мы , вероятно , можем поставить его под-Wextra
. Если вы явно включите какое-то подмножество предупреждений,-Wextra
будет сильно зависеть от вашего кода, вашего стиля кодирования и от того, проще ли поддерживать этот список, чем исправить все, что было обнаружено-Wextra
.Из списка предупреждений OP (который включает оба
-Wall
и-Wextra
) только следующие предупреждения не охватываются этими двумя группами (или включены по умолчанию). Первая группа подчеркивает, почему чрезмерная зависимость от флагов явного предупреждения может быть плохой: ни один из них даже не реализован в Clang! Они принимаются в командной строке только для совместимости с GCC.-Wbad-function-cast
-Wdeclaration-after-statement
-Wmissing-format-attribute
-Wmissing-noreturn
-Wnested-externs
-Wnewline-eof
-Wold-style-definition
-Wredundant-decls
-Wsequence-point
-Wstrict-prototypes
-Wswitch-default
Следующее множество ненужных предупреждений в исходном списке - это те, которые являются избыточными с другими в этом списке:
-Wformat-nonliteral
- Подмножество-Wformat=2
-Wshorten-64-to-32
- Подмножество-Wconversion
-Wsign-conversion
- Подмножество-Wconversion
Есть также выбор предупреждений, которые более категоричны. Они имеют дело с вариантами языкового диалекта, а не с ошибочным или не ошибочным кодом. За исключением того
-Wwrite-strings
, что все это предупреждения для языковых расширений, предоставляемых Clang. Предупреждает ли Clang об их использовании, зависит от распространенности расширения. Clang стремится к совместимости с GCC, и поэтому во многих случаях облегчает это с помощью неявных языковых расширений, которые широко используются.-Wwrite-strings
Как прокомментировал OP, это флаг совместимости от GCC, который фактически изменяет семантику программы. Я глубоко сожалею об этом флаге, но мы должны поддержать его из-за наследия, которое оно имеет сейчас.-Wfour-char-constants
-Wpointer-arith
-Wwrite-strings
Остальные опции, которые фактически включают потенциально интересные предупреждения, таковы:
-Wcast-align
-Wconversion
-Wfloat-equal
-Wformat=2
-Wimplicit-atomic-properties
-Wmissing-declarations
-Wmissing-prototypes
-Woverlength-strings
-Wshadow
-Wstrict-selector-match
-Wundeclared-selector
-Wunreachable-code
Причина, по которой они отсутствуют
-Wall
или-Wextra
не всегда понятна. Для многих из них, на самом деле они основаны на предупреждения GCC (-Wconversion
,-Wshadow
и т.д.) и как таковой Clang пытается имитировать поведение GCC в. Мы постепенно разбиваем некоторые из них на более мелкие и полезные предупреждения. Те, у кого больше шансов попасть в одну из групп предупреждений верхнего уровня. Тем не менее, чтобы выбрать одно предупреждение,-Wconversion
оно настолько широко, что в обозримом будущем оно, скорее всего, останется своей собственной категорией «высшего уровня». Некоторые другие предупреждения, которые имеет GCC, но которые имеют низкую ценность и высокий уровень ложноположительных результатов, могут быть отнесены к аналогичной ничейной земле.Другие причины, по которым их нет в одной из больших групп, включают в себя простые ошибки, очень существенные ложноположительные проблемы и предупреждения в процессе разработки. Я собираюсь изучить ошибки, которые я могу определить. Все они в конечном итоге должны перейти в соответствующий большой флаг или быть удалены из Clang.
Я надеюсь, что это проясняет ситуацию с предупреждениями в Clang и дает некоторую информацию для тех, кто пытается выбрать набор предупреждений для их использования или использования их компанией.
источник
-Wno
необходимости выключать,warn_no_constructor_for_refconst
PITA использует Boost.ConceptCheck и тому подобное: github.com/boostorg/concept_check/blob/…Я не использую Clang, но я надеюсь, что вы тоже не против того, чтобы узнать мое мнение. Я также использую максимальный уровень предупреждений (полагаю, что это означает -Wall) и трактую предупреждения как ошибки (я предполагаю, что это означает -Werror), и я отключаю только те несколько предупреждений, которые не имеют особого смысла. На самом деле, меня раздражает тот факт, что некоторые очень полезные предупреждения не выдаются компилятором C #, и для их просмотра необходимо запустить специальные инструменты анализа кода. Мне нравятся предупреждения, потому что они помогают мне обнаруживать небольшие ошибки и ошибки в моем коде. Они мне так нравятся, что когда выдается предупреждение для фрагмента кода, который, как я знаю, является правильным, я все равно реорганизую этот фрагмент кода, так что предупреждение не будет выдано, вместо того, чтобы отключить предупреждение, или --even хуже - позволить этому появиться и игнорировать это. Я думаю, что предупреждения потрясающие,
источник
-Wall
предоставляет только основные предупреждения. Многие существующие предупреждающие флаги не охвачены-Wall
, поэтому список в моем вопросе.Обычно я использую настройки Xcode по умолчанию для нового проекта; это обеспечивает хороший баланс между полезным и раздражающим. Любой конкретный список предупреждений и другие параметры компилятора будут основываться в значительной степени либо на личных предпочтениях, либо на требованиях проекта, поэтому я не думаю, что есть большая польза от попыток просмотреть ваш список и привести аргументы за или против конкретных предупреждений. Если это работает для вас, отлично. Если вы обнаружили, что допустили ошибку, которую компилятор должен был бы обнаружить, и вам нужна помощь в этом в будущем, найдите опцию компилятора, чтобы предупредить об этом и включить ее.
Одна вещь, которую многие программисты рекомендуют, - это включить опцию «Рассматривать предупреждения как ошибки» (-Werror), чтобы предотвратить успешное завершение сборок при наличии каких-либо предупреждений.
источник
-Werror
. На самом деле, так как я использую Clang, я установил все эти предупреждения с помощью прагмы (#pragma лязг диагностики), и они установлены к фатальным ошибкам, так это то же самое , как-Werror
:)Я думаю, что лучшим доказательством того, что люди заботятся о предупреждениях, является тот факт, что они существуют и широко используются. Я твердо убежден, что чем больше ошибок будет обнаружено во время компиляции, тем лучше. Если бы это не было широко распространенным убеждением, все использовали бы слабые динамически типизированные языки, потому что их компиляторы или интерпретаторы дают вам гораздо больше свободы действий. Наоборот, даже на языках сценариев использование
strict
флагов популярно. В статических строго типизированных языках люди не только-Wall -Werror
часто используют , но они часто находят предупреждения настолько ценными, что им нужно еще больше , поэтому они платят за инструменты статического анализа, такие как Coverity , единственной целью которых является предоставление предупреждений.Это не значит, что нет хулителей. Многие разработчики считают, что предупреждения работают против них в краткосрочной перспективе, а не для них в долгосрочной перспективе, и не пытаются решить основную проблему. Следовательно, вы видите прекрасный код, похожий на этот фрагмент, с которым я столкнулся вчера:
источник
-Werror
и фактически игнорируют предупреждения, выдаваемые компилятором. Или, если они делают, они просто придерживаются-Wall
. Большинство флагов, которые я предоставляю в своем вопросе, не охвачены-Wall
, и я лично думаю, что они тоже важны. Так я просто параноик? ; )Вообще, я больше склоняюсь к -Wall и определенно верю, в том числе и к -Werror. Модуль никогда не должен был ожидать предупреждений. В конечном итоге вы получите еще одно предупреждение и пропустите его. И это будет на самом деле проблема.
Это также зависит от того, добавляете ли вы «-Wall -Werror» в новый или старый проект. Если он новый, то сделайте это и потребуйте совершенства, иначе вы, вероятно, будете в течение нескольких дней или недель редактировать и тестировать. Я только что сделал это на более старом, но небольшом проекте, и потратил два или три дня на удаление предупреждений. Я думаю, что код теперь чище.
Другими словами, попробуйте и посмотрите.
похотливый
источник
-Wall
и-Werror
, я думаю, вам следует перечитать вопрос. Многие флаги предупреждения не покрыты-Wall
. В любом случае, спасибо за ответ.