﻿# Что такое MISRA и как её готовить

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

![0702_About_MISRA_ru/image1.png](https://import.viva64.com/docx/blog/0702_About_MISRA_ru/image1.png)

Многие наши читатели слышали о том, что PVS\-Studio поддерживает классификацию своих предупреждений согласно стандарту MISRA\. На данный момент PVS\-Studio [покрывает](https://pvs-studio.ru/ru/pvs-studio/sast/misra/) более 100 правил MISRA C: 2012 и MISRA С\+\+: 2008\.

Данная статья имеет цель убить сразу трёх зайцев:

1. Рассказать, что такое MISRA для тех, кто ещё не знаком с данным стандартом;
1. Напомнить миру embedded\-разработки о том, на что мы способны;
1. Помочь глубже войти в курс дела новым сотрудникам, которые тоже будут в дальнейшем разрабатывать наш MISRA\-анализатор;

Надеюсь, у меня получится сделать это интересно\. Итак, приступим\!

## История появления MISRA

История MISRA началась достаточно давно\. Тогда, в начале 90\-x, правительственная программа Великобритании под показательным названием "Safe IT" выделяла финансирование для различных проектов, так или иначе связанных с безопасностью электронных систем\. Сам проект MISRA \(Motor Industry Software Reliability Association\) был основан ради создания руководства по разработке ПО для микроконтроллеров в наземных транспортных средствах – в машинах, в общем\.

Получив финансирование от государства, коллектив MISRA взялся за работу, и уже к ноябрю 1994 года выпустил своё первое руководство: "[Development guidelines for vehicle based software](https://www.semanticscholar.org/paper/development-guidelines-for-vehicle-based-software/f7ab6319c0ab1fb546e406a3f65463cd0e5d2f0c?p2df)"\. Это руководство еще не было привязано к конкретному языку, но должен признать: работа была проделана внушительная и касалась она, наверное, всех мыслимых аспектов разработки встраиваемого ПО\. Кстати, недавно разработчики этого руководства отпраздновали 25\-летие столь важной для них даты\.

Когда финансирование от государства закончилось, члены MISRA решили продолжить работать вместе на неформальной основе – так продолжается и по сей день\. По сути, MISRA \(как организация\) – это содружество заинтересованных сторон из различных авто\- и авиастроительных индустрий\. Сейчас этими сторонами являются:

* Bentley Motor Cars
* Ford Motor Company
* Jaguar Land Rover
* Delphi Diesel Systems
* HORIBA MIRA
* Protean Electric
* Visteon Engineering Services
* The University of Leeds
* Ricardo UK
* ZF TRW

Весьма сильные игроки рынка, не правда ли? Не удивительно, что их первый связанный с языком стандарт – MISRA C – стал общепринятым среди разработчиков критически важных встраиваемых систем\. Чуть позже появился и MISRA C\+\+\. Постепенно версии стандартов обновлялись и дорабатывались, чтобы охватывать новые возможности языков\. На момент написания этой статьи актуальными версиями являются MISRA C: 2012 и MISRA C\+\+: 2008\.

## Философия и примеры правил

Самые отличительные черты MISRA – это невероятное внимание к деталям и крайняя дотошность в обеспечении безопасности\. Авторы не просто собрали в одном месте все пришедшие в голову "дыры" C и C\+\+ \(как, например, авторы CERT\) – они тщательно проработали международные стандарты этих языков и выписали все мыслимые и немыслимые способы ошибиться\. А потом взяли и сверху дописали правил про читаемость кода – это чтобы в уже чистый код было сложнее внести новую ошибку\.

Чтобы понять масштаб серьезности, рассмотрим несколько правил, взятых из стандарта\.

С одной стороны, есть много хороших, годных правил, которым стоит следовать вообще всегда, независимо от того, для чего предназначен ваш проект\. По большей части они призваны устранить неопределенное/неуточненное/зависимое\_от\_реализации поведение\. Например:

* Не используйте значение неинициализированной переменной
* Не используйте указатель на FILE после закрытия потока
* Все non\-void функции должны возвращать значение
* Счетчик цикла не должен иметь floating\-point тип
* \.\.\.и т\.д\.

С другой стороны, есть правила, польза которых лежит на поверхности, но которые \(с точки зрения обыкновенных проектов\) нарушить уже не так грешно:

* Не используйте goto и longjmp
* Каждый switch должен заканчиваться default 
* Не пишите недостижимый код
* Не используйте вариативные функции
* Не используйте адресную арифметику \(кроме _\[\]_ и _\+\+_\)
* \.\.\.

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

Мы не хотим, чтобы из\-за программной ошибки какой\-нибудь рентгеновский аппарат [облучал пациентов дозой в 20 000 рад](https://pvs-studio.ru/ru/blog/posts/0438/), поэтому обычных "повседневных" правил уже недостаточно\. На кону стоят человеческие жизни и огромные деньги, и необходимо включать дотошность\. Здесь и выходят на сцену остальные правила MISRA:

* Суффикс 'L' в литерале всегда должен быть заглавным \(маленькую 'l' можно перепутать с единичкой\)
* Не используйте оператор "запятая" \(она увеличивает шанс допустить ошибку\)
* Не используйте рекурсию \(небольшой по размеру стек микроконтроллера может легко переполниться\)
* Тела операторов _if_, _else_, _for_, _while_, _do_, _switch_ должны быть завернуты в фигурные скобки \(потенциально можно допустить ошибку при [неправильном выравнивании кода](https://pvs-studio.ru/ru/docs/warnings/v2507/)\)
* Не используйте динамическую память \(потому что есть шанс неудачного выделения её из кучи, особенно в микроконтроллерах\)
* \.\.\.и много, много таких правил\.

Зачастую у людей, которые сталкиваются с MISRA, складывается мнение, что философия стандарта заключается в "запретить вон то и запретить вот это"\. На самом деле, это так, но лишь отчасти\. 

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

В MISRA C правила делятся на три основных категории: Mandatory, Required и Advisory\. Mandatory – это правила, которые нельзя нарушать ни под каким предлогом\. Например, в этот раздел входит правило "не используйте значение неинициализированной переменной"\. Required\-правила менее строги: они допускают возможность отклонения, но только если эти отклонения тщательно документируются и письменно обосновываются\. Остальные правила входят в категорию Advisory – это правила, которым следовать не обязательно\.

В MISRA C\+\+ немного по\-другому: там отсутствует категория Mandatory, и большинство правил принадлежит к категории Required\. Поэтому, по сути, вы имеете право нарушить любое правило – только не забывайте документировать отклонения\. Также там есть категория Document – это обязательные к выполнению правила \(отклонения не допускаются\), которые связаны с общими практиками вроде "Каждое использование ассемблера должно быть задокументировано" или "подключаемая библиотека должна соответствовать MISRA C\+\+"\.

## Что еще есть

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

Во\-первых, стандарт содержит достаточно тщательное описание подоплёки: ради чего создавался стандарт, почему был выбран именно C или C\+\+, достоинства и недостатки этих языков\.

Про достоинства этих языков мы прекрасно знаем\. Да и про недостатки, в общем\-то, тоже :\) Чего только стоят высокая сложность, неполная спецификация стандартом и синтаксис, позволяющий ну очень легко ошибиться, а потом долго искать ошибку\. Например, можно случайно написать так:

```cpp
for (int i = 0; i < n; ++i);
{
  do_something();
}
```

Всё\-таки есть шанс, что человек не заметит [лишней точки с запятой](https://pvs-studio.ru/ru/docs/warnings/v529/), верно? Еще можно написать [вот так](https://pvs-studio.ru/ru/docs/warnings/v559/):

```cpp
void SpendTime(bool doWantToKillPeople)
{
  if (doWantToKillPeople = true)
  {
    StartNuclearWar();
  }
  else
  {
    PlayComputerGames();
  }
}
```

Хорошо, что и [первый](https://pvs-studio.ru/ru/docs/warnings/v2507/), и [второй](https://pvs-studio.ru/ru/docs/warnings/v2561/) случай легко отлавливаются правилами MISRA \(первое \- MISRA C: 13\.4/MISRA C\+\+: 6\.2\.1, второе \- MISRA C: 13\.4/MISRA C\+\+: 6\.2\.1\)\.

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

Также в конце имеются приложения, в которых содержатся: краткий список и сводная таблица правил, небольшой перечень уязвимостей C/С\+\+, пример документации отклонения от правила, а также несколько чек\-листов, призванных помочь вам не запутаться во всей этой бюрократии\. 

Как видите, MISRA – это не просто набор правил, а практически целая инфраструктура по написанию безопасного кода для встраиваемых систем\. 

## Использование в ваших проектах

Представим ситуацию: вы собрались написать программу для какой\-нибудь очень нужной и ответственной встраиваемой системы\. Или у вас уже есть программа, но её нужно "перенести" на MISRA\. Как же проверять ваш код на соответствие стандарту? Неужели придется делать это вручную? 

Ручная проверка кода – занятие непростое и потенциально невыполнимое\. Мало того, что каждому ревьюверу пришлось бы тщательно высматривать каждую строчку кода, так еще и знать стандарт придется чуть ли не наизусть\. Ужас\!

Поэтому сами разработчики MISRA для проверки вашего кода советуют использовать статический анализ\. Ведь, по сути, статический анализ – это автоматизированный процесс code review\. Вы просто запускаете анализатор на вашей программе и через несколько минут получаете отчет о потенциальных нарушениях стандарта\. То, что нужно, ведь так? Вам останется лишь просмотреть лог и исправить срабатывания\.

Следующий вопрос: в какой момент начинать использовать MISRA? Ответ простой: чем раньше, тем лучше\. В идеале – до того, как вы вообще начнёте писать код, потому что MISRA предполагает следование стандарту в течение всей жизни вашего кода\.

Конечно, не всегда имеется возможность писать по MISRA с самого начала\. Например, часто бывает, что проект уже частично или полностью реализован, но заказчик пожелал, чтобы проект соответствовал стандарту\. В таком случае вам придется заняться основательным рефакторингом уже имеющегося кода\. 

Вот тут\-то и всплывает подводный камень\. Я бы даже сказал, всплывает подводный валун\. Что будет, если вы возьмёте статический анализатор и проверите "обыкновенный" проект на соответствие стандарту MISRA? Спойлер: вы можете испугаться\.

![0702_About_MISRA_ru/image2.png](https://import.viva64.com/docx/blog/0702_About_MISRA_ru/image2.png)

Нажмите на картинку для увеличения\.

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

Что же с этим делать? Неужели придется отложить все дела и сесть за исправление всех старых срабатываний?

Мы знаем, что при первой проверке проекта достаточно часто появляется много срабатываний, и разработали решение, которое поможет вам получать пользу от анализатора сразу, не останавливая работу\. Называется это решение "suppress\-базы"\. 

Suppress\-базы – это механизм PVS\-Studio, который позволяет массово подавить сообщения анализатора\. Если вы впервые проверяете проект и обнаруживаете там несколько тысяч срабатываний – вы просто добавляете их в suppress\-базу, и при следующем прогоне анализатор выдаст вам ноль предупреждений\.

Таким образом, вы сможете продолжить писать и изменять код в обычном режиме, и при этом будете видеть предупреждения только о тех ошибках, которые были внесены в проект только что\. При этом вы будете получать максимальную пользу от анализатора сразу здесь и сейчас, не отвлекаясь на разгребание старых ошибок\. Несколько кликов – и анализатор внедрен\! Почитать подробную инструкцию об этом вы можете [здесь](https://pvs-studio.ru/ru/docs/manual/0032/)\. 

У вас наверняка может возникнуть вопрос: "Подождите, а что делать со спрятанными срабатываниями?" Ответ довольно простой: не забывать о них и потихонечку исправлять\. Можно, например, заложить suppress\-базу в систему контроля версий и допускать только те коммиты, которые не увеличивают количество срабатываний\. Таким образом, постепенно ваш "подводный валун" рано или поздно сточится и от него не останется и следа\.

Окей, анализатор внедрен и теперь мы готовы продолжать\. Что делать дальше? Понятное дело – работать с кодом\. Но что нужно, чтобы можно было заявить о соответствии стандарту? Как доказать, что ваш проект соответствует MISRA?

Дело в том, что не существует какого\-то специального "аттестата" о том, что ваш код соответствует MISRA\. Как оговаривает сам стандарт, отслеживание кода на соответствие должно выполняться двумя сторонами: заказчиком ПО и поставщиком ПО\. Поставщик разрабатывает ПО, соответствующее стандарту, и заполняет необходимые документы\. Заказчик же со своей стороны должен удостовериться, что данные из этих документов соответствуют действительности\. 

Если же вы сами являетесь и заказчиком, и разработчиком собственного ПО, то ответственность за соответствие стандарту будет лежать только на ваших плечах :\)

В общем, для доказательства соответствия вашего проекта вам понадобятся документы\-пруфы\. Список документов, которые должны подготовить разработчики проекта, может варьироваться, но MISRA предлагает некоторый набор в качестве эталонного\. Рассмотрим этот набор поподробнее\.

Для заявления о соответствии стандарту вам понадобится несколько вещей:

* Собственно проект, код которого соответствует Mandatory и Required правилам
* План обеспечения соответствия \(guide enforcement plan\)
* Документация по всем предупреждениям компиляторов и статических анализаторов
* Документация по всем отклонениям от Required\-правил
* Резюме о соответствии правилам \(guideline compliance summary\)

Первый из них – план обеспечения соответствия\. Это ваша самая главная таблица, и именно она будет отсылать проверяющего ко всем остальным документам\. В первом её столбике находится список MISRA\-правил, в остальных – отмечается, были ли выявлены какие\-то отклонения от этих правил\. Выглядит эта таблица примерно так:

![0702_About_MISRA_ru/image3.png](https://import.viva64.com/docx/blog/0702_About_MISRA_ru/image3.png)

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

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

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

Таким образом, план обеспечения соответствия – это документ, по которому можно будет найти документацию к любому отклонению, выявленному в вашем коде\. 

Теперь немного про саму документацию отклонений от правил\. Как я уже упомянул, такая документация необходима только для Required\-правил, потому что правила уровня Mandatory нарушать нельзя, а Advisory\-правилам можно не следовать и без всякой документации\.

Если вы решили отклониться от правила, то документация должна содержать:

* Номер нарушенного правила
* Точную локацию отклонения
* Обоснованность отклонения
* Доказательство того, что отклонение не нарушает безопасность
* Потенциальные последствия для пользователя

Как видите, такой подход к документации заставляет серьезно задуматься, стоит ли нарушение того\. Это сделано специально, чтобы нарушать Required\-правила было неповадно :\)

Теперь про резюме о соответствии правилам\. Эту бумагу, пожалуй, будет заполнить легче всего:

![0702_About_MISRA_ru/image4.png](https://import.viva64.com/docx/blog/0702_About_MISRA_ru/image4.png)

Центральный столбик заполняется до того, как приступить к работе с кодом, а самый правый – после того, как ваш проект готов\. 

Вполне резонно задать вопрос: зачем нужно указывать категории правил, если они уже указаны в самом стандарте? Дело в том, что стандарт допускает "повышение" правила в более строгую категорию\. Например, заказчик может попросить вас перенести какое\-нибудь Advisory\-правило в категорию\. Такое "повышение" должно быть сделано до работы с кодом, и резюме о соответствии правилам позволяет явно это отметить\.

С последним столбиком всё просто: достаточно только отметить, используется ли правило, и если да, то имеются ли от него отклонения\. 

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

![0702_About_MISRA_ru/image5.png](https://import.viva64.com/docx/blog/0702_About_MISRA_ru/image5.png)

Итак, вы написали код, тщательно следуя правилам MISRA\. Вы составили план обеспечения соответствия и задокументировали всё, что можно было задокументировать, а также заполнили резюме о соответствии правилам\. Если это действительно так, то вы получили очень чистый, очень читаемый и очень надёжный код, который вы теперь ненавидите :\)

Где теперь будет жить ваша программа? В аппарате МРТ? В обыкновенном датчике скорости или в системе автопилота какого\-нибудь космического спутника? Да, вы прошли через серьёзный бюрократический путь, но это – мелочи\. Разве можно не быть дотошным, когда на кону стоят настоящие человеческие жизни?

Если вы справились и смогли дойти до победного конца, то я искренне вас поздравляю: вы пишете качественный безопасный код\. Спасибо\!

## Будущее стандартов

Напоследок хочется немного рассказать о будущем стандартов\.

На данный момент MISRA живёт и развивается\. Например, в начале 2019 года был анонсирован "The MISRA C:2012 Third Edition \(First Revision\)" – обновленный и дополненный новыми правилами стандарт 2012 года\. Тогда же объявили о грядущем выходе "MISRA C:2012 Amendment 2 – C11 Core" – стандарте 2012 года, в который будут добавлены правила, впервые охватывающие версии языка Си 2011 и 2018 годов\.

Не стоит на месте и MISRA C\+\+\. Как известно, последний стандарт MISRA C\+\+ датируется 2008 годом, поэтому наиболее старшая версия языка, которую он охватывает – это C\+\+03\. Из\-за этого появился еще один стандарт, аналогичный MISRA, и называется он AUTOSAR C\+\+\. Он изначально задумывался как продолжение MISRA С\+\+ и имел своей целью охватить более поздние версии языка\. В отличие от своего вдохновителя, AUTOSAR C\+\+ обновляется два раза в год и на данный момент поддерживает C\+\+14\. Планируется дальнейшее обновление до C\+\+17, а затем C\+\+20, и так далее\. 

К чему я начал про какой\-то другой стандарт? Дело в том, что чуть меньше года назад обе организации объявили об объединении своих стандартов в один\. Теперь MISRA C\+\+ и AUTOSAR C\+\+ станут единым стандартом, и теперь они будут развиваться вместе\. Я думаю, это отличная новость для разработчиков, пишущих под микроконтроллеры на C\+\+, и не менее отличная новость для разработчиков статических анализаторов\. Любимой работы наперёд еще много\! :\)

## Заключение

Сегодня мы с вами многое узнали про MISRA: почитали историю её возникновения, изучили примеры правил и философию стандарта, рассмотрели всё необходимое для использования MISRA в ваших проектах, и даже немного заглянули в будущее\. Надеюсь, теперь вы лучше понимаете, что такое MISRA и как её готовить\!

По старой традиции оставлю здесь ссылку на наш статический анализатор PVS\-Studio\. Он способен находить не только отклонения от стандарта MISRA, но еще и [огромнейший спектр](https://pvs-studio.ru/ru/blog/examples/) ошибок и уязвимостей\. Если вам интересно самостоятельно попробовать PVS\-Studio – [скачайте](https://pvs-studio.ru/ru/pvs-studio/download/) демонстрационную версию и проверьте свой проект\.

На этом моя статья подходит к концу\. Желаю всем читателям счастливого Нового года и веселых новогодних выходных\!

## Дополнительные ссылки

1. [PVS\-Studio \- статический анализатор кода](https://youtu.be/c5sJd4Abr8c)\.
1. [PVS\-Studio & KEIL 5 совместная работа](https://youtu.be/9h7yObKAADU)\.