链接器报ltc E108错误:符号在fsdata.o与fs.o中重复定义
解决链接器重复定义符号问题
链接器错误信息
ltc E108: multiple definitions of symbol "file__img_sics_gif" in both "fsdata.o" and "fs.o" ltc E108: multiple definitions of symbol "file__404_html" in both "fsdata.o" and "fs.o" ltc E108: multiple definitions of symbol "file__index_html" in both "fsdata.o" and "fs.o" make: *** [makefile:95: Ethernet_1_KIT_TC397_TFT.elf] Error 1
问题背景
重复定义的符号是fsdata.c中定义的结构体数组:
const struct fsdata_file file__img_sics_gif[] = {{ file_NULL, data__img_sics_gif, data__img_sics_gif + 16, sizeof(data__img_sics_gif) - 16, FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, }}; const struct fsdata_file file__404_html[] = {{ file__img_sics_gif, data__404_html, data__404_html + 12, sizeof(data__404_html) - 12, FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, }}; const struct fsdata_file file__index_html[] = {{ file__404_html, data__index_html, data__index_html + 12, sizeof(data__index_html) - 12, FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, }}; #define FS_ROOT file__index_html #define FS_NUMFILES 3
当前在fs.c中直接包含了fsdata.c文件,通过宏FS_ROOT访问这些结构体,而fsdata_file结构体的定义位于fs.h:
struct fsdata_file { const struct fsdata_file *next; const unsigned char *name; const unsigned char *data; int len; u8_t flags; #if HTTPD_PRECALCULATED_CHECKSUM u16_t chksum_count; const struct fsdata_chksum *chksum; #endif /* HTTPD_PRECALCULATED_CHECKSUM */ };
核心原因
fsdata.c被单独编译生成了fsdata.o,同时fs.c又直接包含fsdata.c,导致编译fs.c时这些结构体被再次定义,最终两个目标文件中存在完全相同的符号,链接时触发冲突。
解决方法
方法1:改用头文件声明(推荐)
这是C语言项目解决符号重复定义的标准做法:
- 创建
fsdata.h头文件,在里面用extern声明符号并保留宏定义:
#ifndef FSDATA_H #define FSDATA_H #include "fs.h" extern const struct fsdata_file file__img_sics_gif[]; extern const struct fsdata_file file__404_html[]; extern const struct fsdata_file file__index_html[]; #define FS_ROOT file__index_html #define FS_NUMFILES 3 #endif /* FSDATA_H */
- 修改
fs.c,将原来的#include "fsdata.c"替换为#include "fsdata.h" - (可选)在
fsdata.c开头添加#include "fsdata.h",确保声明与定义的一致性
这样编译时,fsdata.o包含符号的唯一定义,fs.o通过头文件的extern声明引用这些符号,不会出现重复定义。
方法2:禁止单独编译fsdata.c
如果不想调整头文件结构,可以修改Makefile,移除fsdata.c的编译规则:
- 找到Makefile中目标文件列表(通常是
OBJS变量),删除其中的fsdata.o - 确保只有
fs.c包含fsdata.c,这样结构体只会被编译一次,不会生成重复的目标文件
这种方式不够规范,仅适合临时快速修复。
方法3:添加静态修饰(不推荐)
给fsdata.c中的结构体定义加上static关键字:
static const struct fsdata_file file__img_sics_gif[] = {{...}};
这样符号作用域被限制在单个目标文件内,链接时不会冲突,但会导致fsdata.o和fs.o中各存一份相同的数据,浪费内存,因此不推荐。
内容的提问来源于stack exchange,提问作者Rana Zeeshan
相关产品推荐
相关产品推荐

