Соответствие MISRA: 2020, которое объединяет и разъясняет множество руководств, которые ранее были рассредоточены по публикациям руководств по кодированию MISRA C и C++, содержит список правил и руководств MISRA.
Чтобы узнать больше об основах MISRA, нажмите это, чтобы прочитать другую историю о MISRA 101…
Нарушения и дефекты
В MISRA-C:2012 содержится 143 правила и 16 «директив» (то есть положений, соблюдение которых является более двусмысленным или относится к процессу или процедурным вопросам), каждое из которых классифицируется как обязательное, обязательное или рекомендательное. Они делятся на две категории: единая единица перевода и система. Правила далее подразделяются на категории «Решаемые» и «Неразрешимые».
- Обязательные правила должны соблюдаться всегда,
- Обязательныерекомендации должны соблюдаться, если нет особых исключений,
- Следует соблюдать рекомендательные стандарты, но они менее строго соблюдаются.
«Дефекты больше похожи на предупреждения независимого кода, исходящие от компиляторов C, такие как затенение переменных, запись без дальнейшего чтения и т. д.»
Подход
Во-первых, я бы рекомендовал вам сортировать ошибки в соответствии с их качествами и масштабами. Если ваш инструмент не справляется со своей задачей, вы можете настроить его несколькими способами. Организация результатов в соответствии с областью действия файла стала проще. Разделите их, чтобы вы могли работать только с одним исходным файлом.
После этого вы можете установить его как свою семью, под семьей я имею в виду нарушения правил. Большинство инструментов с окружением делают это разделение. Таким образом, вы можете просто нажать фильтрацию и увидеть результат в том виде, в котором мы хотим.
Все готово, теперь мы можем выбрать ошибку и сфокусироваться на ней. Сосредоточившись на ошибке, вы эффективнее исправите все остальные. Вы увидите одну и ту же ошибку в разных частях кода по порядку.
Всегда записывайте числа. Вы можете легко забыть количество полученных ошибок, поэтому всегда записывайте количество чисел, где оно увеличивается, а где уменьшается. Потому что, пока вы наслаждаетесь исправлением, вы можете сделать снежный ком для других…
Пора приближаться!
Давайте перейдем к некоторым нарушениям
MISRA C:2012 Правило 2.3
"Если тип объявлен, но не используется, то рецензенту неясно, является ли этот тип избыточным или он был оставлен неиспользованным по ошибке".
int16_t unusedtype ( void ) { typedef int16_t local_Type; /* Non-compliant */ return 61; }
Ну, я слышу, как вы говорите: «Это слишком просто». Давайте рассмотрим более сложную задачу.
MISRA C:2012 Правило 14.4
"Управляющее выражение оператора if и управляющее выражение оператора итерации должны иметь по существу логический тип".
#include <stdbool.h> #include <stdlib.h> #define TRUE 1 typedef _Bool bool_t; extern bool_t flag; int a; uint32_t i; float b; void doesntmatter(void){ while(TRUE){} /* Compliant */ while(flag){} /* Compliant */ if(b){} /* Non-compliant - int is not boolean */ if(a != 0){} /* Compliant */ for(int i=-10; i;i++){} /* Non-compliant - int is not boolean */ for(int i=0; i<10;i++){} /* Compliant */ }
Если вы столкнулись с этим нарушением, вы должны просто проверить, является ли управляющее выражение логическим или нет. Проверьте наличие typedef и extern, если вы используете стандартные библиотеки.
Я считаю, что все разработчики могут решить такие нарушения, поэтому я не собираюсь стоять на такого рода нарушениях. Давайте проверим наиболее часто встречающиеся нарушения.
MISRA C:2012 Правило 10.8
"Значение составного выражения не должно быть приведено к другой категории основного типа или более широкому основному типу".
Я гарантирую, что вы решите десятки существенных ошибок типа. 10.8 — одно из сложных правил.
typedef int uint32_t; float fl; uint32_t sum; sum = (uint32_t)((fl + 100f)/(50f); //Non-Compliant sum = (uint32_t)((float)(fl + 100f)/(50f); //Compliant
Мы приводим его два раза, потому что правило говорит нам не приводить составное выражение, и мы обманываем его, приводя «приведенное» выражение. Я называю это двойным броском :).
Модели основных типов в основном решаются путем приведения переменных, но вы должны быть осторожны, чтобы не приводить только для того, чтобы избавиться от ошибки. Следите за размером и данными, которые нужно удалить.
MISRA C:2012 Правило 6.1
«Битовые поля должны быть объявлены только с соответствующим типом».
int b:3; // Noncompliant - may have the range of values 0..7 or -4..3 float c:3.0f; // Noncompliant - both type and values are not fit _Bool d:true; // Compliant uint8_t e:5; // Noncompliant - may have the range of values 0..11 or -6..5 uint8_t f:1; // Compliant
По сути, существуют соответствующие типы для определений битовых полей, объявлений и операций. Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией _Bool, signed int, unsigned int или какой-либо другой реализацией. определенный тип
Правило 20.7 MISRA C:2012
«Выражения, полученные в результате раскрытия макропараметров, должны быть заключены в круглые скобки».
Допустим, это наш заголовок «types».
#ifndef INC_TYPES_H_ #define INC_TYPES_H_ #define RBIT01(P) (P >> 1u) #define RBIT02(P) (P >> 2u) ... #define LBIT01(P) (P << 1u) #define LBIT02(P) ((P) << 2u) //P is in parentheses ... #endif #include "types.h" uint8_t eightbits = 0xA5; RBIT01(eightbits); // Noncompliant RBIT02(eightbits); // Noncompliant LBIT01((eightbits)); // Compliant LBIT02(eightbits); // Compliant because P is in parentheses in decleration LBIT01(RBIT02(eightbits)); // Noncompliant RBIT01((RBIT02((eightbits)))); // Compliant
Итак, здесь, я полагаю, вы видели некоторые из самых раздражающих нарушений MISRA C и столкнулись с ними в этой истории. Я могу гарантировать, что большинство этих правил делают ваш код более безопасным, поскольку вы можете понять это, сосредоточив внимание на некоторых правилах и их результатах на возникающих возможностях.
Заботиться. Код безопаснее!