MISRA-C2012
6 分钟阅读
概述
XWOS的代码,大致遵循 MISRA-C:2012 规范进行编写,但有些 MISRA-C:2012 的规则不利于 编写操作系统,XWOS的代码趋向于选择更优的性能以及尝试使用更新的语言特性。
本文将详细描述 MISRA-C:2012 检查的方法,以及 MISRA-C:2012 规范的符合程度。
MISRA-C:2012 规范的检查方法
使用 cppcheck
工具的 misra
插件。
cppcheck -I. -I$(XWOS_ARCH_DIR) -I$(XWOS_CPU_DIR) -I$(XWOS_SOC_DIR) -I$(XWOS_BRD_DIR) \
--force --addon=misra --cppcheck-build-dir=$(CPPCHECK_OUT) \
--template=gcc --inline-suppr --suppressions-list=xwbs/util/cppcheck/misra-c2012-suppressions.txt
-i ignore_path src_path
MISRA-C:2012 规范的符合程度
全局禁用的规则
-
uninitvar
- 禁用原因:误报。实际上未初始化变量,编译器会当成错误来处理。
-
misra-c2012-1.4
: Emergent language features shall not be used- 禁用原因:作为一个长期持续维护的项目,XWOS在新版本中会偏向于引入新的语言特性。
-
misra-c2012-2.3
: A project should not contain unused type declarations- 禁用原因:操作系统作为一个 生态系统 的基本环境,其中定义的类型、宏、函数、符号等可能在各种衍生项目中被用到。
-
misra-c2012-2.4
: A project should not contain unused tag declarations- 禁用原因:操作系统作为一个 生态系统 的基本环境,其中定义的类型、宏、函数、符号等可能在各种衍生项目中被用到。
-
misra-c2012-2.5
: A project should not contain unused macro declarations- 禁用原因:操作系统作为一个 生态系统 的基本环境,其中定义的类型、宏、函数、符号等可能在各种衍生项目中被用到。
-
misra-c2012-3.1
: The character sequences/*
and//
shall not be used within a comment- 禁用原因:XWOS内使用doxygen来抓取注释生成文档,文档中如果出现URL,必然会出现
//
,例如https://...
,除此种情况,禁止在注释中出现//
。
- 禁用原因:XWOS内使用doxygen来抓取注释生成文档,文档中如果出现URL,必然会出现
-
misra-c2012-5.9
: Identifiers that define objects or functions with internal linkage should be unique- 禁用原因:包含
static inline
内联函数的头文件多处使用时,内联函数被认为重复定义。
- 禁用原因:包含
-
misra-c2012-8.7
: Functions and objects should not be defined with external linkage if they are referenced in only one translation unit- 禁用原因:XWOS提供的API并不一定被自己使用,对于 MISRA-C2012 规范的检查工具,可能会因为只检查到一次符号而报错。
-
misra-c2012-8.9
: An object should be defined at block scope if its identifier only appears in a single function- 禁用原因:有些数据定义为全局,是为了链接时放在特定的段。
-
misra-c2012-11.3
: A cast shall not be performed between a pointer to object type and a pointer to a different object type- 禁用原因
-
- XWOS中各类型的原子操作和位操作是根据位宽转换为8位、16位、32位、64位基本类型来实现的;
-
- 动态内存管理;
-
- C语言面向对象。
-
- 禁用原因
-
misra-c2012-11.4
: A conversion should not be performed between a pointer to object and an integer type- 禁用原因
-
- 在指令和寄存器级别的代码;
-
xwcc_derof()
宏的实现;
-
- 动态内存管理;
-
- C语言面向对象。
-
- 禁用原因
-
misra-c2012-11.5
: A conversion should not be performed from pointer to void into pointer to object- 禁用原因
-
- 动态内存管理;
-
- 通讯协议协议的变长消息;
-
- 回调函数的用户参数是个泛型指针。
-
- 禁用原因
-
misra-c2012-11.6
: A cast shall not be performed between pointer to void and an arithmetic type- 禁用原因
-
- XWOS将
-1
至-4095
的指针值当作错误码指针。但是指针是一个无符号整数。 因此是以补码形式表示。-1
即0xFFFFFFFF
,-4095
即0xFFFFF001
。
- XWOS将
-
- 动态内存管理。
-
- 禁用原因
-
misra-c2012-15.1
: The goto statement should not be used- 禁用原因:XWOS只在下面两种情况下使用
goto
。-
- XWOS内某些比较核心的算法(例如红黑树),会使用
goto
来提高效率。
- 1.1. 因为这类代码在整个内核中被大量使用,效率是优先考虑的重点;
- 1.2. 这类代码被验证得最充分,稳定性与安全性最高。
- XWOS内某些比较核心的算法(例如红黑树),会使用
-
- XWOS使用
goto
来处理出错时的代码返回。
- 2.1. 如果代码中包含了大量的操作,每个操作都有返回值,若使用
if...else...
将使得嵌套特别深。使用goto
能使得代码更美观易读; - 2.2. 如果代码中包含了大量的操作,每个操作都有对应的反操作,操作与反操作需要像 “栈” 结构一样先进后出,使用
if...else...
很容易 遗漏反操作或将反操作的顺序搞错,但使用goto
就可完美解决这一问题。
- XWOS使用
-
- 禁用原因:XWOS只在下面两种情况下使用
/* 如果包含大量操作,使用 `if...else...` 将使得代码行过长,
* 并且anti_operationX() 很容易写错位置或者遗漏。
*/
int func1(void)
{
rc = operation1();
if (0 == rc) {
rc = operation3();
if (0 == rc) {
rc = operation8();
if (0 == rc) {
rc = operation2();
if (0 == rc) {
rc = operation6();
if (0 == rc) {
rc = operation5();
if (0 == rc) {
} else {
anti_operation6();
}
} else {
anti_operation2();
}
} else {
anti_operation8();
}
} else {
anti_operation3();
}
} else {
anti_operation1();
}
} else {
}
return rc;
}
/* 使用 `goto` 将避免 `if...else...` 上述的两个问题。*/
int func2(void)
{
rc = operation1();
if (rc < 0) {
goto err_operation1;
}
rc = operation3();
if (rc < 0) {
goto err_operation3;
}
rc = operation8();
if (rc < 0) {
goto err_operation8;
}
rc = operation2();
if (rc < 0) {
goto err_operation2;
}
rc = operation6();
if (rc < 0) {
goto err_operation6;
}
rc = operation5();
if (rc < 0) {
goto err_operation5;
}
return rc;
anti_operation5();
err_operation5:
anti_operation6();
err_operation6:
anti_operation2();
err_operation2:
anti_operation8();
err_operation8:
anti_operation3();
err_operation3:
anti_operation1();
err_operation1:
return rc;
}
-
misra-c2012-17.1
: The features of <stdarg.h> shall not be used- 禁用原因:不应该完全禁止语言特性。
-
misra-c2012-18.8
: Variable-length array types shall not be used- 禁用原因:变长数组是C99标准引入的特性,XWOS在新版本中会偏向于引入新的语言特性。
-
misra-c2012-19.2
: The union keyword should not be used- 禁用原因:
- 编写操作系统时不可避免地需要将内存地址转换为不同类型的指针,使用
union
可以避免直接对void *
进行转换,提高可读性。
- 编写操作系统时不可避免地需要将内存地址转换为不同类型的指针,使用
- 禁用原因:
-
misra-c2012-20.9
: All identifiers used in the controlling expression of#if
or#elif
preprocessing directives shall be#define
’d before evaluation- 禁用原因:检测工具会误报,但XWOS的代码是遵循此规则的。
-
misra-c2012-21.1
: **#define
and#undef
shall not be used on a reserved identifier or reserved macro name**- 禁用原因:C语言将任何以
_
开头的符号作为保留,但有些符号来自于编译器的扩展语法,例如__attribute__((x))
,通常将它们定义为两个_
开头的宏来使用, 以显示它们和正常的变量、函数、宏的区别。
- 禁用原因:C语言将任何以
-
misra-c2012-21.3
The memory allocation and deallocation functions of<stdlib.h>
shall not be used- 禁用原因:完全禁止动态内存管理不利于引入高级语言。 仅当安全等级非常高时才禁止动态内存管理,相应的一些功能也不可被使用,例如Lua语言。
-
misra-c2012-21.6
: The Standard Library input/output functions shall not be used- 禁用原因:
stdio.h
的函数在XWOS内被重新定义过。
- 禁用原因:
-
misra-c2012-21.10
: The Standard Library time and date functions shall not be used- 禁用原因:
time.h
的函数在XWOS内被重新定义过。
- 禁用原因:
部分文件禁用的规则
-
misra-c2012-2.7
: There should be no unused parameters in functions- 禁用原因:此头文件中包含CPU架构指令级别的函数,这些函数使用内联汇编语法编写,
在C语法层面看起来有些参数未使用,实际上这些参数是根据
EABI
规则通过寄存器在使用。- 适用范围:
xwcd/soc/arm/v6m/armv6m_isa.h
xwcd/soc/arm/v7m/armv7m_isa.h
xwcd/soc/powerpc/e200x/e200x_isa.h
xwcd/soc/riscv/nuclei/riscv_isa.h
- 适用范围:
- 禁用原因:此头文件中包含CPU架构指令级别的函数,这些函数使用内联汇编语法编写,
在C语法层面看起来有些参数未使用,实际上这些参数是根据
-
misra-c2012-5.7
: A tag name shall be a unique identifier- 禁用原因:匿名结构体被认为
tag name
重复是误报。- 适用范围:
xwcd/soc/arm/v6m/armv6m_isa.h
xwcd/soc/arm/v7m/armv7m_isa.h
xwcd/soc/powerpc/e200x/e200x_isa.h
xwcd/soc/riscv/nuclei/riscv_isa.h
xwcd/ds/uart/common.h
xwcd/ds/uart/controller.h
xwcd/ds/soc/chip.h
xwos/lib/xwbop.c
xwos/mp/skd.h
xwos/up/skd.h
xwos/mp/thd.h
xwos/up/thd.h
xwos/mp/sync/obj.h
xwos/up/sync/obj.h
xwos/mm/mempool/objcache.h
xwos/mm/mempool/page.h
xwmd/isc/xwssc/protocol.h
xwmd/libc/newlibac/lock.c
xwmd/libc/picolibac/lock.c
- 适用范围:
- 禁用原因:libc要求定义的符号
- 适用范围:
xwmd/libc/newlibac/lock.c
xwmd/libc/picolibac/lock.c
- 适用范围:
- 禁用原因:匿名结构体被认为
-
misra-c2012-5.8
: A tag name shall be a unique identifier- 禁用原因:结构体内部的成员名是在结构体的namespace内的,不会和外面符号发生冲突。
- 适用范围:
xwmd/isc/xwssc/hwifal.h
xwos/mm/mempool/i_allocator.h
xwmd/libc/picolibcac/mem.c
xwos/mm/mempool/page.h
- 适用范围:
- 禁用原因:对LIBC中的标准函数进行重写。
- 适用范围:
xwmd/libc/picolibcac/fops.c
- 适用范围:
- 禁用原因:结构体内部的成员名是在结构体的namespace内的,不会和外面符号发生冲突。
-
misra-c2012-8.4
: A compatible declaration shall be visible when an object or function with external linkage is defined- 禁用原因:误报
- 适用范围:
xwos/ospl/xwosplcb.c
- 适用范围:
- 禁用原因:Rust语言的
ffi
不是在C语言层面进行链接。- 适用范围:
xwmd/xwrust/ffi/*.c
- 适用范围:
- 禁用原因:误报
-
misra-c2012-8.5
: An external object or function shall be declared once in one and only one file- 禁用原因:
xwos/ospl/soc/*.h
是操作系统移植层的代码,对符号再次定义,起到汇总与强调的作用。提示用户移植时需要提供这些符号的定义。- 适用范围:
xwos/ospl/soc/*.h
xwos/lib/xwbop.h
xwos/lib/lfq.h
- 适用范围:
- 禁用原因:误报
- 适用范围
xwmd/libc/newlibac/*.c
xwmd/libc/picolibcac/*.c
- 适用范围
- 禁用原因:
-
misra-c2012-8.6
: An identifier with external linkage shall have exactly one external definition- 禁用原因:误报
- 适用范围
xwmd/libc/newlibac/*.c
xwmd/libc/picolibcac/*.c
- 适用范围
- 禁用原因:误报
-
misra-c2012-8.14
: The restrict type qualifier shall not be used- 禁用原因:对LIBC中的标准函数进行重写。
- 适用范围:
xwmd/libc/newlibac/string.c
xwmd/libc/picolibcac/string.c
xwmd/libc/newlibac/time.c
xwmd/libc/picolibcac/time.c
- 适用范围:
- 禁用原因:对LIBC中的标准函数进行重写。
-
misra-c2012-9.2
: The initializer for an aggregate or union shall be enclosed in braces- 禁用原因:误报
- 适用范围:
xwmd/libc/newlibac/fops.c
xwmd/libc/picolibcac/fops.c
- 适用范围:
- 禁用原因:误报
-
misra-c2012-9.3
: Arrays shall not be partially initialized- 禁用原因:误报
- 适用范围:
xwmd/libc/newlibac/fops.c
xwmd/libc/picolibcac/fops.c
- 适用范围:
- 禁用原因:误报
-
misra-c2012-10.8
: The value of a composite expression shall not be cast to a different essential type category or a wider essential type- 禁用原因:宏定义的表达式是复合的表达式,不得不使用强制类型转换
- 适用范围:
xwos/mm/mempool/page.c
- 适用范围:
- 禁用原因:宏定义的表达式是复合的表达式,不得不使用强制类型转换
-
misra-c2012-11.1
: Conversions shall not be performed between a pointer to a function and any other type- 禁用原因:操作系统抽象层到实现层的必要转换
- 适用范围:
xwos/osal/thd.h
xwos/osal/swt.h
- 适用范围:
- 禁用原因:操作系统抽象层到实现层的必要转换
-
misra-c2012-12.3
: The comma operator should not be used- 禁用原因:XWOS的链表(
xwos/lib/bclst.h
)中的迭代操作宏不得不使用逗号表达式来定义。- 适用范围:
xwos/mp/skd.c
xwos/up/skd.c
- 适用范围:
- 禁用原因:XWOS的链表(
-
misra-c2012-14.2
: A for loop shall be well-formed- 禁用原因:XWOS的链表(
xwos/lib/bclst.h
)中的迭代操作过于复杂,使用宏定义来简化代码。- 适用范围:
xwos/mp/skd.c
xwos/up/skd.c
- 适用范围:
- 禁用原因:XWOS的链表(
-
misra-c2012-15.2
: The goto statement shall jump to a label declared later in the same function- 禁用原因:这部分代码是XWOS低中断延迟的关键代码,必须优先考虑实时性和性能,因此不得不用
goto
来实现。- 适用范围:
xwos/mp/tt.c
xwos/up/tt.c
- 适用范围:
- 禁用原因:误报。
- 适用范围:
xwmd/isc/xwssc/mif.c
- 适用范围:
- 禁用原因:这部分代码是XWOS低中断延迟的关键代码,必须优先考虑实时性和性能,因此不得不用
-
misra-c2012-15.4
: There should be no more than one break or goto statement used to terminate any iteration statement- 禁用原因:这部分代码是XWOS低中断延迟的关键代码,必须优先考虑实时性和性能,因此不得不用
goto
来实现。- 适用范围:
xwos/mp/tt.c
xwos/up/tt.c
- 适用范围:
- 禁用原因:使用率较高的代码只使用一个
break
或goto
影响效率。- 适用范围:
xwos/up/skd.c
xwos/mp/sync/evt.c
xwos/up/sync/evt.c
xwmd/isc/xwssc/hwifal.c
xwmd/isc/xwssc/protocol.c
- 适用范围:
- 禁用原因:这部分代码是XWOS低中断延迟的关键代码,必须优先考虑实时性和性能,因此不得不用
-
misra-c2012-15.5
: A function should have a single point of exit at the end- 禁用原因:函数参数检测的代码被定义为一个宏,其中包含了一个
return
。- 适用范围:
xwmd/isc/xwssc/mif.c
- 适用范围:
- 禁用原因:函数参数检测的代码被定义为一个宏,其中包含了一个
-
misra-c2012-17.2
: Functions shall not call themselves, either directly or indirectly- 禁用原因:这部分代码是XWOS独创的开中断调度技术的关键代码,不得不使用递归函数来实现。此处代码被验证得非常充分,稳定性与安全性不用担心。
- 适用范围:
xwos/mp/skd.c
xwos/up/skd.c
- 适用范围:
- 禁用原因:这部分代码是XWOS独创的开中断调度技术的关键代码,不得不使用递归函数来实现。此处代码被验证得非常充分,稳定性与安全性不用担心。
-
misra-c2012-17.7
: The value returned by a function having non-void return type shall be used- 禁用原因:C库函数
memset()
,memcpy()
等有返回值,但这里并不使用它们。- 适用范围:
xwos/mp/rtrq.c
xwos/up/rtrq.c
xwos/mp/sync/evt.c
xwos/up/sync/evt.c
xwmd/isc/xwcq/xwcq.c
xwmd/isc/xwssc/hwifal.c
xwmd/isc/xwssc/mif.c
xwmd/isc/xwssc/protocol.c
xwmd/libc/newlibac/mif.c
xwmd/libc/picolibcac/mif.c
xwmd/libc/newlibac/mem.c
xwmd/libc/picolibcac/mem.c
- 适用范围:
- 禁用原因:确定不使用返回值的地方,使用
cppcheck-suppress [misra-c2012-17.7]
标注。- 适用范围:
xwos/init.c
xwos/mp/lock/mtx.c
xwos/up/lock/mtx.c
xwos/mp/lock/spinlock.c
xwos/up/lock/seqlock.c
xwmd/isc/xwssc/mif.c
xwmd/isc/xwssc/protocol.c
xwos/mm/mempool/objcache.c
xwos/mm/mempool/allocator.c
xwos/mm/mempool/page.c
- 适用范围:
- 禁用原因:C库函数
-
misra-c2012-17.8
: A function parameter should not be modified- 禁用原因:为了追求效率以及内存使用率,不遵循此规则。
- 适用范围:
xwos/lib/xwbop.c
xwos/mm/bma.c
xwos/mm/mempool/objcache.c
xwos/mm/mempool/page.c
xwos/mm/mempool/allocator.c
xwos/mp/lock/mtx.c
xwos/up/lock/mtx.c
xwmd/isc/xwssc/protocol.c
xwmd/libc/newlibac/string.c
xwmd/libc/picolibcac/string.c
- 适用范围:
- 禁用原因:为了追求效率以及内存使用率,不遵循此规则。
-
misra-c2012-20.7
: Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses- 禁用原因:这部分代码使用宏来模拟C++的函数模板,其中作为类型名的参数不能使用括号封闭起来。
- 适用范围:
xwos/lib/xwaop.h
xwos/lib/xwbop.h
- 适用范围:
- 禁用原因:这部分代码使用宏来定义数组,其中作为数组名参数不能使用括号封闭起来。
- 适用范围:
xwos/mm/bma.h
xwos/mm/mempool/allocator.h
xwmd/isc/xwssc/mif.h
xwmd/isc/xwcq/mif.h
- 适用范围:
- 禁用原因:这部分代码使用宏来模拟C++的函数模板,其中作为类型名的参数不能使用括号封闭起来。
-
misra-c2012-20.10
: The#
and##
preprocessor operators should not be used- 禁用原因:这部分代码使用宏来模拟C++的函数模板,必须使用到
#
和##
。- 适用范围:
xwos/lib/xwaop.h
xwos/lib/xwbop.h
- 适用范围:
- 禁用原因:这部分代码使用宏来模拟C++的函数模板,必须使用到
-
misra-c2012-20.12
: A macro parameter used as an operand to the#
or##
operators, which is itself subject to further macro replacement, shall only be used as an operand to these operators- 禁用原因:这部分代码使用宏来模拟C++的函数模板。
- 适用范围:
xwos/lib/xwaop.h
xwos/lib/xwbop.h
- 适用范围:
- 禁用原因:这部分代码使用宏来模拟C++的函数模板。
-
misra-c2012-21.2
A reserved identifier or macro name shall not be declared- 禁用原因:对LIBC中的标准函数进行重写。
- 适用范围:
xwmd/libc/newlibac/string.c
xwmd/libc/picolibcac/string.c
xwmd/libc/picolibcac/fops.c
xwmd/libc/picolibcac/mem.c
- 适用范围:
- 禁用原因:对LIBC中的标准函数进行重写。
-
misra-c2012-21.4
The standard header file<setjmp.h>
shall not be used- 禁用原因:不应该完全禁止语言特性,XWOS对
<setjmp.h>
提供了支持 。- 适用范围:
xwmd/libc/newlibac/setjmp.c
xwmd/libc/picolibcac/setjmp.c
- 适用范围:
- 禁用原因:不应该完全禁止语言特性,XWOS对