Linker Error: _funcName defined in module XXX.c is duplicated in module XXX.c

本文分享了在BC(Borland C)环境下遇到的链接器错误“_funcName defined in module XXX.c is duplicated in module XXX.c”的解决过程。经过排查,最终发现是因为工程中包含了不必要的头文件导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在编译一个BC(Borlandc)下的工程,发现工程一直提示一些undefined之类的错误。于是把工程里每个文件都complie一遍,然后make,再link。到link的时候,系统提示

“Linker Error: _funcName defined in module XXX.c is duplicated in module XXX.c”

网上找资料,发现基本上都是说重复定义,又找不到重复在那里。终于有一个帖子里说到工程里不需要附加.h文件,只要有.c文件即可。于是照此方法,并重新编译连接通过。执行成功!

希望留个脚印,如果有人发生同样问题也可以参考一下。

*** Using Compiler 'V5.06 update 5 (build 528)', folder: 'D:\Keil_v5\ARM\ARMCC\Bin' Build target 'APP' compiling main.c... linking... APP\APP.axf: Error: L6200E: Symbol rx_buf multiply defined (by usart.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_buf multiply defined (by stm32f1xx_it.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_buf multiply defined (by logic.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_buf multiply defined (by periph.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_buf multiply defined (by schedule.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_buf multiply defined (by system.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_byte multiply defined (by usart.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_byte multiply defined (by stm32f1xx_it.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_byte multiply defined (by logic.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_byte multiply defined (by periph.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_byte multiply defined (by schedule.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_byte multiply defined (by system.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_flag multiply defined (by usart.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_flag multiply defined (by stm32f1xx_it.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_flag multiply defined (by logic.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_flag multiply defined (by periph.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_flag multiply defined (by schedule.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_flag multiply defined (by system.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_count multiply defined (by usart.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_count multiply defined (by stm32f1xx_it.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_count multiply defined (by logic.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_count multiply defined (by periph.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_count multiply defined (by schedule.o and main.o). APP\APP.axf: Error: L6200E: Symbol timeout_count multiply defined (by system.o and main.o). APP\APP.axf: Error: L6200E: Symbol uart_rx_complete multiply defined (by usart.o and main.o). APP\APP.axf: Error: L6200E: Symbol uart_rx_complete multiply defined (by stm32f1xx_it.o and main.o). APP\APP.axf: Error: L6200E: Symbol uart_rx_complete multiply defined (by logic.o and main.o). APP\APP.axf: Error: L6200E: Symbol uart_rx_complete multiply defined (by periph.o and main.o). APP\APP.axf: Error: L6200E: Symbol uart_rx_complete multiply defined (by schedule.o and main.o). APP\APP.axf: Error: L6200E: Symbol uart_rx_complete multiply defined (by system.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_index multiply defined (by usart.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_index multiply defined (by stm32f1xx_it.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_index multiply defined (by logic.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_index multiply defined (by periph.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_index multiply defined (by schedule.o and main.o). APP\APP.axf: Error: L6200E: Symbol rx_index multiply defined (by system.o and main.o). Not enough information to list image symbols. Not enough information to list load addresses in the image map. Finished: 2 information, 0 warning and 36 error messages. "APP\APP.axf" - 36 Error(s), 0 Warning(s). Target not created. Build Time Elapsed: 00:00:04
最新发布
07-22
<think>我们正在处理一个编译错误:ERROR L104:MULTIPLE PUBLICDEFINITIONS。这个错误通常发生在同一个符号(函数或变量)在多个源文件中被定义,导致链接器(Linker)在合并目标文件时发现重复定义。根据错误信息,重复定义的符号包括:SETBIT,_ADC_READ, _ADC_INIT。可能的原因及解决方案如下:1.**重复定义函数**:可能在多个源文件中定义了同名的函数(例如,在main.c和adc.c中都定义了ADC_Read函数),或者在一个头文件中定义了函数(而非声明)。2.**头文件中包含函数定义**:通常头文件应该只包含函数声明(使用extern关键字)和宏定义。如果头文件中直接写了函数体,那么每个包含该头文件的源文件都会定义这个函数,导致重复定义。3. **宏定义冲突**:SETBIT可能是宏,如果在多个地方定义(比如不同的头文件)且定义不一致,也可能导致问题。4.**变量重复定义**:全局变量在头文件中定义(没有使用extern声明),导致多个源文件包含该头文件时都定义了一次。解决方案:步骤1:检查函数定义位置-确保每个函数(如ADC_Read,ADC_Init)只在某一个源文件(.c文件)中定义一次。-在头文件中,应该使用extern声明函数,例如://adc.hextern voidADC_Init(void);extern unsignedint ADC_Read(unsigned charchannel);步骤2:检查宏定义-确保宏(如SETBIT)只在一处定义。如果多个头文件需要,可以放在一个公共头文件中,并使用条件编译防止重复包含。#ifndef_COMMON_H_#define _COMMON_H_#define SETBIT(reg,bit)(reg|= (1<<bit))#endif步骤3:检查全局变量-如果使用了全局变量,在头文件中用extern声明,在某个源文件中定义。步骤4:检查文件包含情况-确保没有在头文件中定义函数(内联函数除外)。步骤5:检查库文件-如果使用了厂商提供的库,确保没有将库的源文件(.c)重复添加到项目中。具体到你的情况,错误中提到了_ADC_READ和_ADC_INIT(注意,编译器可能会在函数名前加下划线),所以重点检查ADC_Read和ADC_Init这两个函数的定义位置。假设你的项目结构如下:-main.c:包含主函数- adc.c:包含ADC初始化函数和读取函数的实现-adc.h:包含ADC函数的声明正确的做法: adc.h: ```c#ifndef _ADC_H_ #define_ADC_H_//函数声明voidADC_Init(void); unsignedint ADC_Read(unsigned charchannel);//宏定义(如果之前没有定义过) #defineSETBIT(reg, bit) (reg |=(1<<bit)) //其他必要的宏...#endif``` adc.c: ```c#include "adc.h"// ADC初始化函数定义void ADC_Init(void){//初始化代码(参考引用[1])ADCTIM=0X3F;ADCCFG =0X2F;ADC_CONTR=0X80;} //ADC读取函数定义unsignedint ADC_Read(unsigned charchannel){//选择通道等操作//参考引用[1]和[2]//注意:根据引用[1],STC8H的ADC结果寄存器是ADC_RES和ADC_RESLADC_CONTR= (ADC_CONTR &0xF0) |0x80| channel; //选择通道并启动ADC_nop_();_nop_();while (!(ADC_CONTR&0x20));//等待转换完成ADC_CONTR&= ~0x20;//清除标志位return (ADC_RES<<8)| ADC_RESL; //12位ADC,返回16位整数,高4位为0} ```main.c: ```c#include "adc.h"void main() {ADC_Init();while(1){unsigned intadc_value =ADC_Read(0);//读取通道0//处理adc_value} }```如果之前你把函数定义放在了头文件中,那么当多个源文件包含这个头文件时,就会导致重复定义。现在将函数定义移到adc.c中,头文件中只保留声明,这样问题应该解决。另外,关于SETBIT,如果你在多个地方定义了相同的宏,也会导致重定义错误。确保只在一个头文件中定义一次,并使用条件编译保护。如果问题仍然存在,请检查:-项目中有没有多个文件定义了同名的函数(比如有两个adc.c?)-是否在头文件中定义了变量?如果是,请改为在源文件中定义,头文件中用extern声明。最后,关于引用[3]提到的时钟配置问题,虽然与当前错误无关,但请注意:系统时钟的配置确实是通过CLKSEL和CLKDIV寄存器完成的,但有些开发板可能使用外部晶振,而代码中配置为内部IRC,需要根据实际硬件调整。不过这个不会导致链接错误。如果按照上述步骤操作后问题解决,请确保所有函数和全局变量都遵循“在头文件中声明,在源文件中定义”的原则。 §§相关问题§§1.如何正确使用extern关键字声明全局变量? 2. C语言中如何避免头文件重复包含? 3. STC8H1K08的ADC读取函数如何实现多通道扫描?</think>### STC8H1K08 ADC编译错误解决方案:ERROR L104 #### 错误含义解析 `ERROR L104: MULTIPLE PUBLIC DEFINITIONS` 表示在链接阶段检测到多个同名符号(函数或变量)被重复定义。具体错误涉及: 1. **SETBIT**:位操作宏定义重复 2. **_ADC_READ**:ADC读取函数重复 3. **_ADC_INIT**:ADC初始化函数重复 #### 根本原因分析 根据引用资料[1][2]和常见开发实践,主要问题来源: 1. **头文件重复包含**:未使用`#ifndef`防护导致头文件多次展开 2. **函数定义在头文件中**:在`.h`文件中直接实现函数而非声明 3. **多模块同名定义**:不同源文件定义了同名函数或变量 4. **库文件冲突**:标准库与用户自定义宏命名冲突 --- ### 系统化解决方案 #### 一、头文件防护(关键修复) 在ADC头文件中添加防护机制: ```c // adc.h #ifndef __ADC_H__ #define __ADC_H__ // 函数声明(非定义!) void ADC_Init(void); unsigned int ADC_Read(unsigned char channel); // 宏定义(避免与库冲突) #define MY_SETBIT(reg, bit) ((reg) |= (1 << (bit))) #endif ``` #### 二、函数实现分离 将函数**定义**移至`.c`文件: ```c // adc.c #include "adc.h" // ADC初始化实现(引用[1]) void ADC_Init(void) { ADCTIM = 0x3F; // 采样时序 ADCCFG = 0x2F; // 配置寄存器 ADC_CONTR = 0x80; // 开启ADC电源 } // ADC读取实现(引用[1][2]) unsigned int ADC_Read(unsigned char channel) { ADC_CONTR = (ADC_CONTR & 0xF0) | channel | 0x80; _nop_(); _nop_(); // 等待稳定 while (!(ADC_CONTR & 0x20)); // 等待转换完成 return (ADC_RES << 8) | ADC_RESL; // 合并12位结果 } ``` #### 三、命名冲突处理 1. **重命名冲突宏**: ```c // 原SETBIT可能冲突,改为自定义前缀 #define ADC_SETBIT(reg, bit) ((reg) |= (1 << (bit))) ``` 2. **避免库函数覆盖**: ```c // 在main.c中检查是否包含冲突库 #undef SETBIT // 取消可能冲突的定义 ``` #### 四、项目结构优化 正确文件包含关系: ```mermaid graph TD main.c --> adc.h adc.c --> adc.h adc.h -. 声明 .-> main.c adc.h -. 声明 .-> adc.c ``` #### 五、链接器配置检查 1. 确保项目中无重复`.c`文件 2. 检查链接器脚本: ```makefile OBJS = main.o adc.o # 勿重复添加adc.c ``` --- ### 验证流程 1. **清理重建**: - 删除所有`.obj`和`.build`中间文件 - 执行完整重新编译 2. **错误消失验证**: - 编译日志中应无L104错误 - 映射文件(map)中检查符号唯一性 3. **功能测试**: ```c // main.c #include "adc.h" void main() { ADC_Init(); while(1) { unsigned int val = ADC_Read(0); // 显示ADC值... } } ``` > **预防措施**: > - 始终使用`#ifndef`头文件防护 > - 遵循"声明在.h,实现在.c"原则 > - 为自定义符号添加项目前缀(如`MYAPP_`) > - 定期执行`Build Clean`操作
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值