>
>
Почему embedded-разработчикам следует и…

Андрей Карпов
Статей: 674

Почему embedded-разработчикам следует использовать статический анализ кода

Решил кратко сформулировать 3 причины, по которым embedded-разработчикам полезны инструменты статического анализа кода программ.

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

Статический анализ кода == удешевление процесса тестирования и отладки устройства. Чем раньше ошибка найдена, тем дешевле её исправление. Статический анализ находит ошибки ещё на этапе написания кода или, по крайней мере, во время ночных запусков на сервере. В итоге, поиск и исправление многих ошибок обходится гораздо дешевле.

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

Вот как один знакомый описывал мне подобную ситуацию:

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

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

И я забываю про это дело. Есть другие большие и более интересные задачи. Тем более, раз они не пришли, значит всё хорошо.

А они пришли. Но только через неделю. Говорят, ничего не понимаем. Всю голову сломали. Не работает наш стенд. Вернее, работает, но не совсем как надо. Мы уже перепаяли его заново и исполнительные электромеханические детали заменили. Не работает... Может, посмотришь? Может, всё-таки, в программе что-то не так...

Открываю код и сразу вижу ошибку в духе:

uchar A[3];
....
for (uchar i = 0; i != 4; i++)
  average += A[i];
average /= 3;

За основу был взят другой мой проект, и код во многом написан методом Copy-Paste. В одном месте я забыл заменить 4 на 3. Мне так стыдно было, что я двух людей заставил проработать впустую неделю."

Вторая причина: обновить программу дорого, невозможно или поздно

Ошибки во встраиваемых устройствах крайне неприятны тем, что их невозможно или почти невозможно исправить, если началось серийное производство. Если уже выпущены сотни тысяч стиральных машин и они разъехались по магазинам, то что делать, если в определённом режиме машина работает неадекватно? В общем-то вопрос риторический и реальных вариантов два:

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

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

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

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

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

Третья причина: программист может не знать, что делает что-то неправильно

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

Статические анализаторы имеют базу знаний о различных паттернах, которые в определённых условиях приводят к ошибке. Поэтому они могут указать программисту на ошибку, о существовании которой он сам бы вряд ли догадался. Примером может служить использование 32-битного типа time_t, что может привести к неправильной работе устройства после 2038 года.

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

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

Заключение

Есть ещё одна причина в обязательном порядке использовать статический анализатор кода. Это когда проект должен соответствовать определённому стандарту разработки программного обеспечения на языке, например, MISRA C. Однако это, скорее, относится к административным мерам, и лежит немного в стороне от обсуждаемой темы.

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

  • Сократить время на поиск и устранение ошибок (пример);
  • Уменьшить вероятность критических ошибок;
  • Уменьшить вероятность необходимости обновления прошивок;
  • Контролировать общее качество кода (рекомендуем дополнительно посмотреть в сторону SonarQube);
  • Контролировать качество работы новых членов команды;
  • Контролировать качество кода сторонних модулей/библиотек.

Нет причин не использовать статический анализ кода, кроме лени и иллюзии превосходства.

Используйте статические анализаторы кода! Их много.

Мы, естественно, предлагаем обратить внимание на наш анализатор кода PVS-Studio, который недавно начал поддерживать ряд ARM-компиляторов.