Keil出现报错 Undefined Symbol XXX 解决办法
Contents
问题描述
已经确认函数所在的头文件已经include进来了
链接时报错:Undefined Symbol XXX(ARM 编译链里常见 L6218E,C51 链是 UNRESOLVED EXTERNAL SYMBOL)
意思:这个问题的意思是出现未定义的符号
问题根源(链接器为什么找不到它)
这要从 C 程序的构建两阶段说起。头文件里放的是“声明”,实现放在 .c 里:#include 只是把声明文本抄进来,让编译器知道函数长什么样、检查调用方式对不对——所以“头文件已经 include 了”只保证编译阶段过得去。编译完每个 .c 变成一个目标文件,里面留着一堆“未决引用”;到链接阶段,链接器要为每个引用找到定义(函数体的目标码),找不到就报 Undefined Symbol。这个错看着像编译报错,实际出在链接阶段。
由此只有两种可能:
- 实现存在,但没参与编译链接——.c 文件没加进工程,或所在的库没链上
- 实现根本不存在——只写了声明没写函数体,或实现被 #if 条件编译排除掉了
解决方案
因为我是keil只是用来编译,Eclipse用来写代码,所以忽略了keil要将新建立的C文件加入到工程中来。 加入函数所在的C文件,问题解决,如果你不是这个问题导致的,那可能就真的是只定义了函数,没有实现函数。
.c文件添加进工程的方法
.c文件的添加方法如下:
右键项目,点击 Manage Project Items
然后找到你放.c文件的文件夹,选择需要添加的.c文件即可

踩坑记录与注意事项
- Include Paths 和加入工程是两回事:前者给编译器找头文件(编译期),后者给链接器找实现(链接期)。只配了路径没加 .c,头文件能找到、链接照样报 Undefined Symbol——这是本问题最常见的误解;
- 条件编译把实现关掉:实现文件整个被 #if 0 或某个没打开的宏开关包住,等于没实现,链接时同样报错;
- C/C++ 混编:.cpp 里调用 C 函数要用 extern “C” 包住声明,否则 C++ 的名字改编(name mangling)让链接器找的是另一个名字;
- 汇编调用 C 函数:目标文件名/段名约定不一致(如 C51 的 ?PR? 段命名)也会表现为符号未解析;
- 多目标(Target)配置:文件加进了 Target1 没加进 Target2,切目标编译就报错,检查当前 Target 的文件列表。
Author 软件开发大郭
LastMod 2022-06-02