Это хорошая идея, чтобы исключить предупреждения компилятора?

В прошлом я работал с -Wall и другими ключами для gcc, чтобы устранить все предупреждения компилятора для проектов, в которых я участвовал. Точно так же в Perl я всегда программирую с use strict и использую предупреждения (и часто также -T). ), чтобы попытаться добиться наилучшего качества кода, какое только возможно. Я понимаю, что несколько лет назад группа портировщиков Perl усердно работала над тем, чтобы сам perl (интерпретатор Perl) компилировался чисто под gcc со всеми включенными предупреждениями. Очевидно, они считали, что это хорошая идея для качества кода. Я также понимаю, что в настоящее время программисты Perl добавляют в свой код еще больше предупреждений с помощью Perl::Critic, который предупреждает их, когда они нарушают рекомендации, описанные в книге Damian Conway Perl Best Practices (и, я думаю, из других источников).

У меня всегда было хорошее мнение о коде, который я очистил таким образом, но иногда я не мог избавиться от ощущения, что часть работы была потрачена впустую. Например, более десяти лет назад на моих вводных курсах C меня учили запускать функцию main() следующим образом:

void main(void) {

Это было минимально и могло использоваться только тогда, когда вы не возвращали значение и не обращались к своим аргументам. В этом случае она работает просто отлично, но предупреждения gcc сообщат вам, что эта функция действительно должна выглядеть так:

int main(int args, char* argv) {

Я, должно быть, набрал пару сотен неиспользуемых строк int args, char* argv в тот день. Действительно ли я сделал свой код лучше или просто стал короче?

Сейчас я программирую на Java в Eclipse, и наш проект имеет десятки тысяч предупреждений. Я хотел бы их почистить. Некоторые из них особенно трудно понять и устранить, но потихоньку я учусь. Некоторые из них мне приходилось обрабатывать с помощью директив компилятора для подавления предупреждений (обычно в крошечных минимальных методах, чтобы исключить плохую практику игнорирования предупреждений), но я также нахожу способы справиться с ними.

Стоит ли это времени программиста? Будет ли проект действительно лучше, если вы будете отслеживать каждое предупреждение компилятора?

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

Примечание: дубликат этот вопрос


person skiphoppy    schedule 04.02.2009    source источник
comment
десятки тысяч предупреждений?! Гиз, развлекайся.   -  person Ed S.    schedule 05.02.2009
comment
Нашел ваш вопрос, потому что проект, над которым я недавно работаю, также имеет тысячи предупреждений. Даже сборка EAR всегда выдает 9 предупреждений (все о проприетарном API Sun). Я игнорирую их, но гарантирую отсутствие предупреждений в тех частях кода, к которым прикасаюсь лично (редактирую или создаю). Во всяком случае, большую часть времени. Других, работающих над проектом, вообще не интересуют предупреждения (пока это работает, все в порядке) и говорят друг другу просто закрывать глаза на каждое предупреждение, занимаясь только ошибками.   -  person ADTC    schedule 30.01.2013


Ответы (14)


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

Самый простой способ получить и сохранить код без предупреждений — просто всегда компилировать с параметром -Werror (/WX в Visual Studio) или его эквивалентом.

person JesperE    schedule 04.02.2009

Стоит ли это времени программиста? Будет ли проект действительно лучше, если вы будете отслеживать каждое предупреждение компилятора?

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

person MSN    schedule 04.02.2009
comment
Или, что еще важнее, правильность. Прямо сейчас я работаю над проектом, который выдает 1271 предупреждение. Я добавляю функцию, так как это важнее, чем исправление предупреждений, верно? Когда я закончу свою функцию, я действительно замечу, что теперь есть 1283 предупреждения? Какие из 12 предупреждений, которые я добавил, важны, поскольку они влияют на правильность или производительность? Я никогда не узнаю, потому что я не смотрю на них ... Я полностью потерял чувствительность, видя 1200 с чем-то предупреждений каждый раз, когда я строю. - person MikeB; 13.11.2019

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

Существуют устаревшие системы, в которых некоторые (многие или все) компоненты не имеют специального сопровождающего, а большие части системы практически неизвестны. Исправление предупреждений компилятора в таком неизвестном коде может потребовать значительного объема кода (поскольку для каждого предупреждения необходимо понимать код вместе с его контекстом) и вводит возможный источник ошибок (некоторый код зависит от неопределенных поведение). А поскольку такие унаследованные системы редко имеют обширное тестовое покрытие, вы не можете даже полагаться на тесты, чтобы уведомлять вас о регрессиях.

person Joachim Sauer    schedule 04.02.2009
comment
Очень хороший момент. Исправление предупреждений в унаследованном коде не должно осуществляться вслепую. Есть много рисков, связанных с этим. - person Steve Rowe; 05.02.2009
comment
Это правильное замечание, но я думаю, что если вы не хотите модифицировать унаследованный код, вам следует как можно избирательнее отключать соответствующее предупреждение, желательно с комментарием, объясняющим, почему. Оставлять предупреждение о загрязнении вывода сборки по-прежнему стоит избегать. - person JesperE; 22.09.2015
comment
Все, что вы говорите, это то, что иногда процесс исправления предупреждений не может быть выполнен до тех пор, пока не будут устранены другие проблемы в кодовой базе (например, отсутствие активных владельцев, тестов или документации). - person MikeB; 10.11.2019
comment
@MikeB: это разумный способ взглянуть на это, но иногда он складывается таким образом, что стоимость решения этих других проблем несопоставима с исправлением предупреждений компилятора. - person Joachim Sauer; 11.11.2019

Есть два совместимых прототипа для main в C.

int main(void)

и

int main(int argc, char **argv)

void main(void) технически некорректен, хотя может поддерживаться некоторыми компиляторами как расширение стандарта.

Итак, в вашем конкретном случае вы можете использовать короткое объявление main и, если оно соответствует требованиям, оно не вызовет предупреждения.

person CB Bailey    schedule 04.02.2009

да. Даже мелочи стоит исправлять. Вот почему. Некоторые, как в примере с main, который вы упомянули, вероятно, не стоит исправлять сами по себе, но они в совокупности. Большинство предупреждений компилятора избавят вас от прямых проблем в долгосрочной перспективе. Это баги, ожидающие своего появления (или даже происходящие сейчас). Чтобы найти их, вам нужен простой способ их заметить. Если вы исправите все предупреждения, то каждое новое предупреждение станет красным флажком, и его будет легко заметить. Если вы исправите все критические проблемы, но оставите некоторые из них, такие как «основная», в покое, вы пропустите новые критические проблемы.

Что легче запомнить? Что любое предупреждение должно быть исправлено или что у вас вчера было 23 нерелевантных предупреждения в этой кодовой базе, и поэтому, если вы видите 24, вам нужно пойти посмотреть?

В кодовой базе, над которой я работаю, мы говорим компилятору генерировать ошибки для всех предупреждений. Это вынуждает нас исправлять их и сохраняет код в гораздо лучшей форме. Если когда-нибудь появляется предупреждение, которое действительно не стоит исправлять, всегда есть #pragma, чтобы заставить его исчезнуть. Таким образом, у вас все еще есть яркая линия на провал.

person Steve Rowe    schedule 04.02.2009

Да, сделайте это..

Буквально вчера я сделал это для проекта на работе. При удалении предупреждений я столкнулся с двумя проблемами, которые оказались настоящими ошибками.

Это был C-проект, и в одном источнике он назывался sqrt (квадратный корень). Я получил следующее предупреждение:

test.c:4: warning: implicit declaration of function 'sqrt'

Оказалось, что кодер забыл включить правильный заголовочный файл, и квадратный корень вызывался с целыми аргументами, а не с плавающей запятой. Это было явно неправильно и не то, что он имел в виду.

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

Кстати, исправление предупреждений заняло у меня около ... 4 часов ... Это ничто по сравнению со временем, которое потребовалось, чтобы написать все это.

person Nils Pipenbrinck    schedule 04.02.2009

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

У нас есть много кода, который был написан до Java 1.5 и дженериков. Он все еще работает. Eclipse также генерирует буквально тысячи предупреждений о непараметризованных коллекциях. Практически все эти коллекции ограничены по объему; они никогда не сломаются. Но подождите, вы можете спросить; как насчет нескольких коллекций, которые не ограничены по объему? Не рискуете ли вы, что коллекция где-то содержит экземпляр чего-то, что никогда не должно туда попадать?

Ответ таков: большая часть этого кода также не изменилась. Это наследие; никакой новый код не модифицирует эти коллекции, и этот код используется годами без проблем. Он все еще находится в нашей кодовой базе, и нам придется поддерживать его в случае обнаружения ошибки, но на практике он выполнил свою работу. Трата времени, необходимого для параметризации всех этих универсальных коллекций, отнимет время у других необходимых проектов.

Обратите внимание на оговорки здесь, а затем:

  • Код использовался в течение длительного времени, об ошибках не сообщалось.
  • Код не подвергается какой-либо существенной правке.

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

person Paul Brinkley    schedule 04.02.2009
comment
Проблема с этим подходом заключается в том, что предупреждения стабильного кода загрязняют вывод вашего компилятора и затрудняют распознавание новых и соответствующих предупреждений. Если, как вы говорите, рассматриваемый код является устаревшим и стабильным, то лучшим подходом было бы отключить предупреждения в определенных экземплярах, а не оставлять их в обычном выводе компилятора. - person Nathan; 10.01.2021
comment
Я симпатизирую. Прошли годы, но я даже помню, как поднимал эту тему. Было бы здорово просто игнорировать определенные экземпляры, чтобы новые выделялись и решались, но это означало бы просмотр буквально пары тысяч экземпляров и индивидуальное подавление каждого из них. // Идеальным решением в этом случае, вероятно, была бы возможность подавлять все текущие экземпляры этого типа в массовом порядке и оставлять после этого отчет с предупреждением, но в то время мы не видели такой функции. - person Paul Brinkley; 11.01.2021
comment
Хм. Как бывший технический директор/директор по информационным технологиям, честно говоря, мне кажется, что написать небольшую программу, которая реализует «идеальное» решение, описанное на основе списка файлов, кодов ошибок и номеров строк, должен сделать старший разработчик за полдня; потенциальная экономия тысяч человеко-часов за счет объективного восстановления метрической тонны полезности компилятора. - person Nathan; 21.01.2021

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

person Illandril    schedule 04.02.2009
comment
IMO, стоит исправлять их все каждый раз, потому что в противном случае вы не обязательно заметите, когда генерируются новые (возможно, более важные) предупреждения! - person mghie; 04.02.2009
comment
Время, необходимое компилятору для вывода предупреждений, совершенно и совершенно неинтересно в этом вопросе. - person JesperE; 04.02.2009
comment
Время, необходимое компилятору для вывода предупреждений, — это время, которое не было потрачено на разработку. Для небольшого количества предупреждений и нечастых сборок это тривиально. Если у вас есть десятки тысяч предупреждений и вы создаете много раз в день... это складывается. - person Illandril; 05.02.2009

Eclipse, IntelliJ и другие современные системы контроля качества кода имеют огромное количество доступных предупреждений.

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

Однако многие предупреждения, вероятно, являются ложными. Некоторые предупреждения от Eclipse касаются таких вещей, как микрооптимизация или стилистические придирки. Это означает, что некоторые из ваших очисток должны касаться настроек вашего инструмента, а не изменений кода или локализованных директив подавления.

person Darron    schedule 04.02.2009

Мое мнение. да.

Как ты сказал в конце. Это помогает сделать реальные ошибки более заметными.

Когда вы запускаете сценарий Perl cgi, который выводит предупреждения на сервере Apache, предупреждения регистрируются в журнале error.log. Зачем тратить пространство. Исправьте предупреждения.

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

person J.J.    schedule 04.02.2009

Ваш пример — прекрасная иллюстрация того, почему нельзя игнорировать предупреждения. void main(void) — недопустимый прототип (но int main(void) работает!)), и ваш код может не работать на некоторых компиляторах. Ваш компилятор был достаточно хорош, чтобы указать на это.

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

Рассматривайте предупреждения как ошибки. Исключения существуют (есть одно в компиляторе VB.NET, касающееся неинициализированных типов значений), но они чрезвычайно редки. И если вы когда-нибудь столкнетесь с одним из этих исключений, вы узнаете его.

person Konrad Rudolph    schedule 04.02.2009

Вы всегда должны стараться, чтобы при компиляции не появлялись предупреждения. Таким образом, новые предупреждения привлекают внимание. (Самый разочаровывающий мой опыт с этим был связан с компилятором AIX C++ в 2002 году, который выдал сотни предупреждений для кода, который даже не был сильно шаблонизирован.)

Знайте, что означает каждое предупреждение. В вашем случае вы должны были ввести стандартный int main(), а не неправильный void main(void) или более неуклюжий int main(int argc, char **argv). Устраните все, что можно, и подавите предупреждения, которые вы считаете приемлемыми.

Возможно, вы не захотите исправлять каждое предупреждение. Как говорит Сауа, есть устаревшие системы, в которых исправление предупреждений совершенно опасно, и сложные системы, такие как CGAL, где вы также не хотите возиться с кодом. При преобразовании наших приложений для работы под 64-разрядными версиями я обнаружил случаи, когда я мог устранить предупреждение только с помощью приведения, что потенциально могло вызвать другие проблемы. Мы подавили это предупреждение.

person David Thornley    schedule 04.02.2009

Просто чтобы добавить предупреждения, вот что разработчик gnome использует в своем коде:

http://blogs.gnome.org/otte/2008/12/22/warning-options/

person ZeD    schedule 04.02.2009

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

Однако, если они это сделают и увидят много предупреждений, всегда ли эти предупреждения существовали, или они неправильно установили компилятор на свой ПК?

По крайней мере, если есть правило (и галочка в контрольном списке, если вы его используете), согласно которому код должен компилироваться без предупреждений, вы избегаете этой двусмысленности.

(* Кто-то еще может включать вас в будущем).

person Steve Melnikoff    schedule 04.02.2009