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

ARM GCC 10.3/13.x使用-Os优化时函数指针传参异常问询

问题描述

在Cortex-M7平台下,使用-Os编译选项编译代码时,通过函数指针调用指定地址的函数(+1适配Thumb模式)出现参数传递异常。相关代码如下:

//Some code above...
memset(.....)

uint32_t (*caller)(uint32_t taskid, ...);
caller = (uint32_t(*)(uint32_t, ...))((uint32_t)0x08020000 + 1U);
for (size_t i = 0; i < 3; ++i) {
    caller(i);
}

函数被调用3次,但函数内部接收到的参数i并非预期的0、1、2,而是垃圾值、0、1;关闭-Os编译选项后该问题消失。查看反汇编发现循环被展开,且指令顺序被重排:

memset(shared_ram, 0x00, sizeof(*shared_ram));
 8000968:   2000        movs    r0, #0
        caller(i);
 800096a:   4d1a        ldr r5, [pc, #104]  ; (80009d4 <main+0xc0>)
    memset(shared_ram, 0x00, sizeof(*shared_ram));
 800096c:   6018        str r0, [r3, #0]
 800096e:   6058        str r0, [r3, #4]
 8000970:   6098        str r0, [r3, #8]
        caller(i);
 8000972:   47a8        blx r5
 8000974:   2001        movs    r0, #1
 8000976:   47a8        blx r5
 8000978:   2002        movs    r0, #2
 800097a:   47a8        blx r5

编译参数如下:

-fdata-sections -ffunction-sections --specs=nano.specs -Wl,--gc-sections  -g -mthumb -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -Og -g3 -ggdb -fno-eliminate-unused-debug-symbols -fdata-sections -ffunction-sections -Wall -Wextra -Wpedantic -Wno-unused-parameter -Os -std=gnu11

注:Cortex-M7缓存未启用。

请问这是编译器bug吗?

问题分析与结论

这不是编译器bug,问题根源在于编译器优化逻辑与代码的ABI兼容性冲突:

  1. 从反汇编可见,-Os开启的激进优化(指令重排)打乱了执行顺序:原本应先给r0赋值0再调用caller,但实际是先加载函数指针到r5,接着执行memset的内存写入(全程使用r0),之后才调用caller——此时r0的值已被memset操作覆盖,导致第一次调用传递了垃圾值。
  2. 函数指针被声明为可变参数(...),编译器会按ARM可变参数ABI处理调用逻辑,同时认为memset与caller的参数设置无依赖关系,因此允许指令重排;关闭-Os后优化程度降低,指令顺序符合代码逻辑,问题消失。
解决方案

可通过以下方式修复:

  • 修正函数指针声明:若被调用函数为固定参数,将指针声明改为匹配形式,比如uint32_t (*caller)(uint32_t taskid);,让编译器明确参数寄存器的依赖关系,避免重排破坏参数传递。
  • 插入优化屏障:在memset与caller调用之间添加__asm__ __volatile__("" ::: "memory"),阻止编译器对两段代码进行重排。
  • 局部禁用优化:在包含该循环的函数上添加__attribute__((optimize("O0"))),强制该函数不使用-Os优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:35:01