我有一个先前编译过的c ++程序,但在使用Jamfiles后,该程序不再编译,ld
发出duplicate symbol error
。在连续恢复到原始Jamfiles之后,运行bjam clean
,手动删除对象,并从gcc前端的clang切换到MacO 10.6.7上的gcc 4.2.1,这种情况持续存在。
该程序的简化说明是main.cpp
和四个文件a.h,cpp
和b.h,cpp
,它们被编译成一个链接到main.o
的静态库。 main.cpp
和b.cpp
两者都依赖于包含违规符号off.h
的文件,通过两个不同的中间文件,但a.h
和a.cpp
都不依赖于任何文件方式off.h
。
在你提问之前,我确保所有文件都包含在多个定义保护中(#ifndef
,#define
,#endif
),而我确实发现了一个丢失它们的文件,它没有提到off.h
。更重要的是,b.h
不包含引用off.h
的任何内容,只有实现b.cpp
对off.h
进行引用。仅此一点让我感到困惑。
为了增加我的困惑,我能够从off.h
删除对b.cpp
的引用,并且正如预期的那样,它已成功重新编译。但是,当我添加引用时,它也成功编译,并在清除目标文件后继续这样做。我仍然不知道为什么它没有编译,特别是考虑到符号不应该有冲突,我已经阻止了符号重复,并且我已经摆脱了任何先前/不完整的构建。
由于我能够成功编译我的程序,我怀疑我是否能够重现它以测试任何建议。但是,我很好奇这是怎么发生的,如果我将来遇到这种行为,除了我所做的以外什么,我可以做些什么来解决它?
答案 0 :(得分:45)
这通常是在头文件中定义对象的结果,而不仅仅是声明它。考虑:
h.h :
#ifndef H_H_
#define H_H_
int i;
#endif
a.cpp :
#include "h.h"
b.cpp :
#include "h.h"
int main() {}
这将产生重复的符号i
。解决方案是在头文件中声明对象:extern int i;
并在其中一个源代码文件中定义它:int i;
。