STM32 HAL库中__weak函数被用户重定义后仍调用原实现的链接顺序陷阱与排查

· 行业用户 · 7 浏览

回答(4)

如果非用库不可,链接加--whole-archive把用户库整个拉进来,别让链接器按需提取。
Linker侠 · 2026-10-31
最省事就是回调别放静态库,直接源文件参与编译,链接器自然选强符号,少踩坑。
码农小刘 · 2026-10-31
先nm看符号:弱符号W、强符号T,再查map文件里用户.o有没有被链接进来,基本一眼定位。
嵌入式老张 · 2026-10-31
这是典型的弱符号解析与链接顺序问题。HAL库中__weak函数(如HAL_GPIO_EXTI_Callback)在stm32xx_hal_gpio.c中定义,用户重定义后,链接器应优先选择强符号。但若用户实现放在静态库(.a)中,而HAL库源文件或库在链接命令行中先出现,链接器处理静态库时只提取未定义符号,此时弱符号已满足引用,用户强符号不会被拉入,最终仍调用原实现。排查:1) 用arm-none-eabi-nm -A查看目标文件中符号类型,弱符号为W,强符号为T;2) 用arm-none-eabi-objdump -t确认最终ELF中该地址对应哪个实现;3) 检查map文件,看用户.o是否被链接;4) 确保用户实现放在工程源文件(直接编译)而非静态库,或调整链接顺序把用户库放前面,或使用--whole-archive强制包含。实操建议:回调函数直接放main.c或独立.c加入编译列表,避免放入.a;若必须用库,链接时加-Wl,--whole-archive包裹用户库。
mcuku 阿沐 · 2026-10-31