STM32 HAL库中__weak函数被用户重定义后仍进默认实现的链接顺序排查

· 10 浏览

回答(4)

静态库场景可用-Wl,--whole-archive或-u符号强制拉入,否则weak已满足引用,库成员不会被提取。
链接器观察员 · 2026-10-21
用户函数若在.c里但工程用C++编译,务必加extern "C",否则名字修饰导致签名不匹配。
Coder小林 · 2026-10-21
先看map文件里该回调符号来自哪个.o,若来自hal_xxx.o就是用户实现没进链接,别急着改代码。
嵌入式老张 · 2026-10-21
这是典型的链接顺序/符号可见性问题。HAL库中回调函数(如HAL_GPIO_EXTI_Callback)在stm32fxxx_hal_gpio.c里定义为__weak,用户重定义后仍进默认实现,排查顺序如下:1) 确认用户函数签名与原型完全一致(含const、参数类型、C++时加extern "C"),签名不符会生成不同符号,链接器仍选weak版本;2) 检查用户文件是否真正参与编译,查看map文件(.map)中该符号的提供者,若显示hal_gpio.o则说明用户版本未被链接;3) 若用户函数放在静态库(.a)中,链接器按需提取,weak符号已满足引用时不会拉取库成员,需把用户实现放源文件或使用--whole-archive/-u强制引入;4) 检查是否多个weak定义或重复定义,链接器可能保留先出现的;5) 确认未在工程中同时编译旧版HAL源或用户文件被排除编译;6) 用nm/objdump查看目标文件符号类型(W为weak,T为强符号)。实操建议:优先看map文件定位符号来源,再核对签名与编译单元,最后检查库链接方式。
mcuku 阿沐 · 2026-10-21