Как избежать подводных камней статического анализа


17

Я работаю в компании, которая набрала 11 баллов на тесте Джоэла - по крайней мере, на бумаге.

На практике, однако, ничего не работает так хорошо, как ожидалось, и проект был на DEFCON 1 в течение полугода. Теперь большинство моих сверстников счастливы, если могут вернуться домой в 6 вечера - в воскресенье.

Одна из очевидных хороших практик, которые показались мне неработающими, - это использование инструментов статического анализа. Проект отслеживает как предупреждения gcc -Wall, так и собственный и очень дорогой инструмент "C / C ++" .

Предупреждения Gcc чаще всего указывают на реальные (если в большинстве случаев безобидные) ошибки.

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

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

Результат:

  1. Люди добавляют приведения типов к каждому значению и к каждому аргументу, скрывая реальные проблемные несоответствия типов в процессе.
  2. Люди рассказывают об ошибках или используют другую проблематичную языковую функцию (strlen вместо sizeof, strncpy вместо strcpy и т. Д.)
  3. Предупреждения молчат.
  4. Отчеты об ошибках начинают появляться.

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

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

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


1
Примечание: у GCC кроме «-Wall» есть также опция «-Wextra» и еще больше предупреждений, которые по какой-то причине не включены в обе метаопции. Смотрите документы для получения дополнительной информации. В общем, в каждой опции есть упоминание, если она включена метаопцией. Поэтому, чтобы найти все, что не включено, вы можете выделить во всех документах слова «-Wall» и «-Wextra», и вы увидите, что еще не используется.
Привет, Ангел,

Я также добавил бы, что мне интересно, что GCC не включил большую часть «-Wextra» в «-Wall». Поверьте мне, некоторые из этих флагов очень полезны ; по крайней мере, эти предупреждения освобождают меня от часов отладки.
Привет, Ангел,

1
Я удивлен, что никто не упомянул обзоры кода в ответах. Для меня люди, пытающиеся проникнуть в некоторые дрянные хаки, были бы заблокированы обзорами кода ...
dyesdyes

Ответы:


16

На практике, однако, ничего не работает так хорошо, как ожидалось, и проект был на DEFCON 1 в течение полугода. Теперь большинство моих сверстников счастливы, если могут вернуться домой в 6 вечера - в воскресенье.

Это, безусловно, хороший кусок вашей проблемы. Инженер-программист не может работать продуктивно более 40 часов в неделю. Если вы превысите это, вы нанесете серьезный ущерб своей способности работать - до такой степени, что даже 80 часов работы в неделю приносят очень мало пользы проекту, а иногда проекты могут даже регрессировать, потому что команда вносит больше ошибок, чем они могут исправить. Если вы работали 60 часов в неделю или больше в течение полугода, тогда вся ваша команда нуждается в хорошем долгом перерыве, чтобы вернуться на 40 часов в неделю. Вы не можете решить что-либо с рабочей силой, которая вряд ли способна нанести удар по клавиатуре, потому что они так перегружены работой.

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

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


Не могли бы вы предоставить ссылку на исследование с ограничением в 40 часов в неделю?

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

5
Два небольших, но ИМХО важных исправления: ограничение в 40 часов в неделю является приблизительным средним значением, и правило применяется только в течение длительных периодов времени. Это нормально, что команда тратит дополнительные часы до важного срока, а затем восстанавливается (возможно, даже с выходными). Кроме того, лимит варьируется между людьми и с течением времени - некоторые могут работать 43 часа в неделю без проблем, другие только 35, и один более продуктивен в некоторые недели, чем другие. Однако использование значительного сверхурочного времени более двух недель подряд действительно вызовет серьезные проблемы.
Петер Тёрёк

13

Я работаю в компании, которая набрала 11 баллов на тесте Джоэла - по крайней мере, на бумаге.

Этот тест слегка уместен для компаний-разработчиков программного обеспечения. Я не понимаю шумиху по этому поводу. Вы можете набрать 12 и все еще иметь 100% программистов дерьма. Люди значат гораздо больше, чем инструменты.

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

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

Для конкретного набора неявных типов типов это происходит из-за некоторых очень распространенных, тонких и опасных ошибок в языке C, вызванных двумя (дебильными) правилами продвижения неявных типов в C. Они формально известны как правила целочисленного продвижения и обычные арифметические преобразования . Я думаю, что менее одного из десяти профессиональных программистов на Си могут объяснить, что делают эти два правила, а что нет. И все же эти правила чрезвычайно фундаментальны и применяются тысячи раз между строк в любой обычной программе на Си.

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

Я бы порекомендовал любому программисту на С прочитать эту главу MISRA-C или, по крайней мере, Google, два упомянутых мной правила продвижения и прочитать о них как можно больше. Вы можете игнорировать статический анализатор только тогда, когда знаете все об этих правилах.

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

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

Легкого пути нет. На самом деле проблема не в инструменте, а в неясном языке Си. На первый взгляд это может показаться простым языком, но между строк происходит множество нелогичных и странных механизмов. И есть также сотни случаев неопределенного / неопределенного / специфического поведения в языке. Большинству из них нужно учиться и избегать.

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


Я с самого начала прошел тест с небольшим количеством соли, но это не инструмент для тестирования программистов, а инструмент для тестирования работодателей. Я полагаю, вы могли бы включить подходящих сотрудников как «лучшие инструменты, которые могут заплатить деньги». И я принимаю ваш ответ, чтобы выбросить инструменты SA, а также нанимать и / или обучать лучше. Первый пункт кажется общим знаменателем.

@qpr Это также не проверяет работодателя, просто готовность работодателя тратить деньги на разработку программного обеспечения. Такие вещи, как процедура найма, корпоративные цели, знание рынка и т. Д. И т. Д. Не упоминаются. Я думаю, что большинство компаний, занимающихся «пузырями в сфере ИТ», в этом тесте набрали бы 12 баллов, а руководство даже не знает, какие продукты разрабатываются, и существует ли вообще какой-либо рынок для них.

4

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

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

Это плохая идея полагаться на инструмент, который генерирует много ложных срабатываний, особенно если вы не можете подавить эти ложные срабатывания. Это поощряет усталых / перегруженных (или ленивых) программистов делать «исправления», чтобы предупреждения исчезли. Если вы не можете выборочно подавлять ложные срабатывания (например, с помощью комментариев) или адаптировать набор правил, тогда вам нужен лучший инструмент. Или, по крайней мере, вы должны использовать его только экономно.

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

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


3

В дополнение к отличному ответу user29079, я хотел бы добавить еще один недостаток языка C, который добавляет к проблеме. Я не знал об этом недостатке, пока не перешел на Java.

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

Что совершенно неверно , так это то, что каждую мелкую штуку нужно исправить любой ценой, изменив код . Именно это и вызвало проблему, которую описывает OP: неудачные попытки поспешно убрать предупреждения, изменив код, который работает просто отлично.

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

Таким образом, это, кажется, случай противоречивых целей; противоречие.

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

У Java есть хорошее решение этой проблемы с @SuppressWarnings( "" )аннотацией. Если вы делаете, скажем, так называемое неконтролируемое преобразование в java, компилятор выдает предупреждение, чтобы обратить ваше внимание на это, вы изучаете его, вы определяете, что это еще один из тех случаев, когда вы знаете, что делаете, таким образом, вы предшествуете оскорбительному заявлению @SuppressWarnings( "unchecked" )аннотацией, которая затрагивает только заявление, которое следует сразу за ним, и вы продолжаете свою жизнь.

Таким образом, предупреждение исчезает, код остается неизменным, и аннотация подавления стоит там, выделенная зеленым цветом подсветкой синтаксиса, чтобы задокументировать тот факт, что происходит сомнительное преобразование, но автор обещает, что это хорошо. (*) Все счастливы.

В java вы можете даже добавлять к функциям отдельные параметры @SuppressWarnings(), чтобы отключить определенное предупреждение, которое может быть выдано только для этого конкретного параметра.

Однако, насколько мне известно, C никогда не поддерживал какой-либо стандартный механизм для выборочного подавления предупреждений в операторах, и некоторые компиляторы, которые реализовали свои собственные проприетарные механизмы, делали это хитро, например, #pragma warning (nnn:N)директивы Microsoft C. Проблема с этими директивами в том, что вам нужно две строки директив, чтобы подавить предупреждение для одного оператора и оставить это предупреждение включенным для следующих операторов. Таким образом, программисты на С очень маловероятны, чтобы усвоить привычку подавлять предупреждение для каждого отдельного оператора, даже если они знают, что это конкретное предупреждение в отношении этого конкретного оператора в порядке.


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


Другими словами, в то время как изменение источника с целью удаления каждого последнего предупреждения является ключом к хорошей практике, изменение скомпилируемого кода - нет, так как оно устраняет простой код, который просто корректен без веской причины. Хорошее различие.
Натан Тагги

2

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

Если программное обеспечение, которое разрабатывает ваша команда, является чем-то важным, от чего зависят человеческие жизни, инструменты статического анализа важны и полезны. Поскольку «стоимость» ошибки, измеряемая деньгами (игнорируя, насколько это цинично), высока, для работы требуются специальные инструменты. Существуют рекомендации для безопасного использования языковых функций как на C, так и на C ++ (прочитайте, чего следует избегать и как далеко его избегать).
Тем не менее, в такой ситуации, когда работники работают в воскресенье, это очень плохая идея, более того, из предоставленного вами контекста я экстраполирую, что небрежная работа нередка. Так что, если это так, проблема очень и оченьбольшой, и ваше руководство пытается решить эту проблему с помощью «лучших» инструментов. К сожалению, это не так. Если я даже близок к тому, чтобы исправить, я бы даже сказал, что вы начали искать другую работу. Плохое программное обеспечение для критически важных задач может преследовать вас и разрушать вашу профессиональную репутацию, не говоря уже о перспективах судебных исков.

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

Если вам нужно управлять командой разработчиков программного обеспечения, которая пишет некоторый код на C или C ++, я бы сказал, сначала определите основные цели проекта. Если написание кода без ошибок имеет первостепенное значение (например, новое супер-классное социальное приложение для iOS и Android не подходит для этого), тогда используйте статический анализ, возможно, даже до формальной спецификации и формальной проверки. Но в этом случае гораздо важнее выбрать хороших программистов и заставить их работать в разумной среде с адекватной рабочей нагрузкой и правильной 40-часовой рабочей неделей.

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

Итог: определите свои цели, затем определите инструменты и процесс, который вы используете, не позволяйте доступным инструментам определять процесс (следовательно, цели), поскольку (плохое) руководство может захотеть вас заставить.


1

Как указано в ответе k.steff, инструменты статического анализа для 'C' полезны, если вы создаете программное обеспечение в критической ситуации (программное обеспечение для самолета), и их необходимо использовать с первого дня (а не после нескольких месяцев разработки, когда возникает невоспроизводимая ошибка ).

Использование таких инструментов на поздних стадиях процесса разработки обычно является признаком неудачного выбора дизайна на ранних этапах процесса.

В некритическом программном обеспечении эти виды инструментов полезны для:
-обеспечения управления, чтобы они чувствовали себя полезными (мы что-то сделали, мы потратили много денег на исправление программного обеспечения). Это дает им действия, которые легко выполнить в отчетах Powerpoint).
- Держите «ядовитых» разработчиков занятыми. Позвольте им настроить инструмент и проанализировать результаты инструмента, чтобы у вас было время исправить их неприятные ошибки.
-принуждение правил кодирования. В этом случае он должен использоваться с первого дня. Но хороший инструмент для проверки кода может быть лучшим выбором.

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


1

Я работаю в компании, которая набрала 11 баллов на тесте Джоэла - по крайней мере, на бумаге.

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

Теперь большинство моих сверстников счастливы, если могут вернуться домой в 6 вечера - в воскресенье.

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

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

Да, есть способ использовать статический анализ кода в разумной манере.

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

Похоже, лица, принимающие решения, путают флаги статического анализа с дефектами приложения.

Неявные приведения также занесены в черный список в их книге стилей.

Это звучит как проблема управленческой компетенции, а не проблема статического анализа.

Результат:

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

Люди рассказывают об ошибках или используют другую проблематичную языковую функцию (strlen вместо sizeof, strncpy вместо strcpy и т. Д.)

Предупреждения молчат.

Отчеты об ошибках начинают появляться.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.