Skip to main content

MISRA C:2025:深入探讨部分变更

新的MISRA C:2025规则已发布。但具体有哪些新增内容和变化?

MISRA C是一套旨在提升安全关键系统中C代码安全性、安全性和可靠性的指南。多年来,MISRA指南已成为开发复杂嵌入式系统时需遵循的最重要标准之一——这些系统在安全性、安全性和可靠性方面容不得丝毫差错。尤其是汽车、医疗和航空航天领域要求软件必须符合MISRA指南。

上一次重大规则更新发生在2023年。最新发布的MISRA C:2025规则集规模并不大——更多是对MISRA C:2023规则的微调——但仍包含一些值得探讨的变化。

MISRA C:2025 中的新指南

MISRA C:2025新增了四条规则

规则 8.18:头文件中不得出现暂定性定义(tentative definitions

该规则防止在开发者难以判断暂定性定义是作为定义还是声明的情况下,导致对象在不同编译单元中被重复创建。

我们通过示例分析。假设某执行文件包含两个变量 a b 的声明int i;int j = 0;,并包含以下头文件:

/* the following is a non-compliant tentative definition */
int32_t i;
/* while the following is a compliant external declaration */
extern int32_t j;

规则 8.19:源文件中不应进行外部声明

该规则旨在通过强制执行清晰的接口来提高可维护性和模块性。特别针对外部变量在头文件中声明但仍属于实现部分的情况,例如:

void uses_externs( void )
{
    /* non-compliant external declared in implementation of uses_externs */
    extern int32_t i;
}

规则 11.11:指针不得隐式与 NULL 比较

扩展了MISRA基本类型系统(essential type system)的覆盖范围,并在适当场景强制使用布尔表达式替代指针。该规则考虑了强制转换和条件语句中的比较,例如以下代码片段均属非合规:

int *ptr; 
/* non-compliant cast to bool */
(bool) ptr;
/* non-compliant comparison in condition */
if(ptr)
{}

规则 19.3:联合体成员在未设置前不得被读取

根据所使用的 C 标准,读取未赋值的联合体成员(inactive union member)会导致实现定义甚至未定义的行为。这对于安全关键系统显然不可接受。

该规则的非合规示例如下:向联合体某个成员写入(使其成为赋值成员(active member))后读取另一个成员,例如:

union
{
    int member1;
    float member2;
} my_union;
/* following line renders member1 the active member */
my_union.member1 = 5;
/* non-compliant usage of the inactive member2 */
if(my_union.member2)
{}

相比 MISRA C:2023 的其他变更

除上述内容外,部分MISRA规则还进行了调整。多条规则得到澄清说明、新增例外情况或重新编号。多个示例被扩展以进一步阐明预期行为。

最后,著名的 "单一退出点 "(single point of exit)规则已被重新分类为 "不适用"(disapplied),表明从MISRA角度不再要求合规且无需强制执行。但开发者需注意,IEC 61508 和 ISO 26262 等其他法规仍鼓励采用类似方法,并可能在某些项目和某些条件下强制执行 MISRA 规则。

结论

虽然MISRA C:2025的变更看似幅度不大,但它们确实确保了 MISRA 与最新发展保持同步,继续为安全关键应用开发提供支持。遵循 MISRA 指南不仅是一个合规性要求,更直接影响代码质量和可维护性,助力开发面向未来的软件。