You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MISRA规则18.3违规疑问:通用启动代码为何触发指针比较限制?

MISRA规则18.3判定启动代码违规的原因与修正方案

首先看触发违规的代码:

extern uint32_t __etext;
extern uint32_t __data_start__, __data_end__;
uint32_t* src = (uint32_t*)&__etext;        // ROM location of code to be copied into ram
uint32_t* dst = (uint32_t*)&__data_start__; // Start of RAM data section

while (dst  < &__data_end__) // Loop until we reach the end of the data section
{
    *dst++ = *src++;
}

为什么这段代码触发MISRA 18.3?

MISRA规则18.3的核心要求是:仅当指针指向同一对象(或同一数组的元素)时,才能使用<、>、<=、>=这类关系运算符。

C标准明确规定,指向不同独立对象(或不同内存区域)的指针进行关系比较属于未定义行为——不同编译器、硬件架构可能会返回不可预知的结果,甚至触发异常。MISRA作为嵌入式系统的安全编码规范,会严格禁止这类存在风险的写法。

而这段启动代码里,__data_start__和__data_end__是链接器脚本定义的独立符号,在C代码语义层面,它们是两个无关的uint32_t类型外部变量,并非同一数组的首尾元素。静态分析工具只会依据C语言语法和语义判断,不会“理解”这是链接器规划的连续内存区域,因此判定为违规。

合规的修正方案

方案1:通过计算内存长度控制循环(无需修改链接器脚本)

放弃指针比较,先算出.data段的总字节数,用循环次数控制复制流程:

extern uint32_t __etext;
extern uint32_t __data_start__, __data_end__;
uint8_t* src_byte = (uint8_t*)&__etext;
uint8_t* dst_byte = (uint8_t*)&__data_start__;
const size_t data_total_bytes = (uint8_t*)&__data_end__ - (uint8_t*)&__data_start__;

for (size_t i = 0; i < data_total_bytes; ++i)
{
    *dst_byte++ = *src_byte++;
}

这里用字节指针计算长度,避免了跨对象的指针比较,完全符合MISRA规则。

方案2:将符号声明为数组类型(需配合链接器脚本)

如果可以调整链接器脚本,把__data_start__和__data_end__定义为数组的边界:

.data :
{
    __data_start__ = .;
    *(.data)
    __data_end__ = .;
} > RAM

然后在C代码里将它们声明为数组指针:

extern uint32_t __data_start__[];
extern uint32_t __data_end__[];
uint32_t* src = (uint32_t*)&__etext;
uint32_t* dst = __data_start__;

// 此时dst与__data_end__属于同一数组的指针,比较合法
while (dst < __data_end__)
{
    *dst++ = *src++;
}

这种方式让静态分析工具识别到两个指针指向同一数组区域,满足规则18.3的例外条件。

内容的提问来源于stack exchange,提问作者user3880296

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:11:05