了解链接器重复符号错误的来源

rco*_*yer 21 c++ linker gcc clang

我有一个先前编译过的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.hfrom 的引用,b.cpp并且正如预期的那样,它已成功重新编译.但是,当我添加引用时,它也成功编译,并在清除目标文件后继续这样做.我仍然不知道为什么它没有编译,特别是考虑到符号不应该有冲突,我已经阻止了符号重复,我已经摆脱了任何先前/不完整的构建.

由于我能够成功编译我的程序,我怀疑我是否能够重现它以测试任何建议.但是,我很好奇这是如何发生的,如果我将来遇到这种行为,除了我所做的以外什么,我可以做些什么来修复它?

Rob*_*obᵩ 47

这通常是在头文件中定义对象的结果,而不是仅仅声明它.考虑:

......:

#ifndef H_H_
#define H_H_
int i;
#endif
Run Code Online (Sandbox Code Playgroud)

a.cpp:

#include "h.h"
Run Code Online (Sandbox Code Playgroud)

b.cpp:

#include "h.h"
int main() {}
Run Code Online (Sandbox Code Playgroud)

这将产生一个重复的符号i.解决方案是在头文件中声明对象:extern int i;并在其中一个源代码文件中定义它:int i;.

  • @ 9000 - 如果它没有像`int i;`或`int i = 17;`这样的行,你_can_`#include`在两个文件中包含相同的标题.它必须只有声明,而不是定义 - `extern int i;`是的. (4认同)
  • 1)在文件范围声明的名称具有外部链接.2)对象可以在多个翻译单元中声明,但必须只定义一次. (3认同)
  • 符号是在标题中内联声明的函数,但缺少关键字`inline`,[this](http://stackoverflow.com/questions/2954256/duplicate-symbol-linker-error-c-help)建议可能是必要.但是,我对你的解决方案的问题是为什么在目标文件`ao`中`int i`以这样的方式暴露,它与`bo`中的那个相冲突?据我所知,这不应该发生.我错过了什么? (2认同)