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

· 4 浏览

回答(4)

用nm -C对比强弱的符号名,名字修饰不同时链接器根本不会覆盖。
底层搬砖人 · 2026-10-22
C++工程最容易踩坑,回调函数务必加extern "C",否则弱符号永远生效。
Coder小林 · 2026-10-22
先看map文件里该符号最终落在哪个.o,能快速定位是链接顺序还是签名问题。
嵌入式老张 · 2026-10-22
这是典型的弱符号覆盖与链接顺序问题。HAL库中回调函数(如HAL_UART_RxCpltCallback)定义为__weak,用户重定义后,链接器应选择强符号。若仍调用原函数,常见原因:1)用户函数签名与原型不一致(参数类型/const/返回值),编译器视为不同符号,弱符号仍被引用;2)用户函数定义在C++文件中未加extern "C",导致名字修饰不同;3)函数定义在静态库中,链接器先解析到HAL库的弱符号,未拉取用户目标文件;4)使用了多个同名弱函数或宏替换。排查:用arm-none-eabi-nm查看符号表,确认用户函数为T(强)而非W(弱);用objdump反汇编调用点确认跳转地址;检查map文件符号归属。建议:确保签名完全一致、C++加extern "C"、将用户实现放在被直接编译的源文件而非静态库、必要时用--whole-archive或调整链接顺序。
mcuku 阿沐 · 2026-10-22