了解链接器重复符号错误的根源
我有一个以前编译过的 c++ 程序,但在使用 Jamfiles 后,程序不再编译,ld
发出 duplicate symbol 错误
.在连续恢复到原始 Jamfile、运行 bjam clean
、手动删除对象以及在 MacOs 10.6.7 上从带有 gcc 前端的 clang 切换到 gcc 4.2.1 之后,这种情况仍然存在.
I have a c++ program that compiled previously, but after mucking with the Jamfiles, the program no longer compiled and ld
emitted a duplicate symbol error
. This persisted after successively reverting to the original Jamfiles, running bjam clean
, removing the objects by hand, and switching from clang with the gcc front end to gcc 4.2.1 on MacOs 10.6.7.
程序的简化描述是有main.cpp
和四个文件ah,cpp
和bh,cpp
,分别是被编译成一个链接到 main.o
的静态库.main.cpp
和 b.cpp
都通过两个不同的中间文件依赖于包含违规符号 off.h
的文件,但是ah
和 a.cpp
都不依赖于 off.h
.
A simplified description of the program is that there is main.cpp
and four files, a.h,cpp
and b.h,cpp
, which are compiled into a static library which is linked to main.o
. Both, main.cpp
and b.cpp
depend on the file containing the offending symbol, off.h
, through two different intermediate files, but neither a.h
nor a.cpp
depend in any way on off.h
.
在你问之前,我确保所有文件都包含在多个定义保护中(#ifndef
、#define
、#endif
),虽然我确实找到了一个缺少它们的文件,但它没有引用 off.h
.更重要的是,bh
不包含任何引用 off.h
的内容,只有实现 b.cpp
对 进行任何引用关闭.h
.仅这一点就让我感到困惑.
Before you ask, I made sure that all files were wrapped in multiple definition guards (#ifndef
, #define
, #endif
), and while I did find a file that was missing them, it did not reference off.h
. More importantly, b.h
does not include anything that references off.h
, only the implementation, b.cpp
, makes any reference to off.h
. This alone had me puzzled.
为了增加我的困惑,我能够从 b.cpp
中删除对 off.h
的引用,并且正如预期的那样,它重新编译成功.但是,当我重新添加引用时,它也编译成功,并在清除目标文件后继续这样做.我仍然不知道为什么它无法编译,特别是考虑到符号不应该发生冲突,我已经防止了符号重复,并且我已经摆脱了任何先前/不完整的构建.
To add to my confusion, I was able to remove the reference to off.h
from b.cpp
and, as expected, it recompiled successfully. However, when I added the reference back in, it also compiled successfully, and continued to do so after cleaning out the object files. I am still at a loss for why it was failing to compile, especially considering that the symbols should not have conflicted, I had prevented symbol duplication, and I had gotten rid of any prior/incomplete builds.
由于我能够成功编译我的程序,我怀疑我能否重现它来测试任何建议.但是,我很好奇这是如何发生的,如果我在未来遇到这种行为,如果有超出我所做的事情,我可以做些什么来解决它?
Since I was able to successfully compile my program, I doubt I'll be able to reproduce it to test out any suggestions. However, I am curious as to how this can happen, and if I run across this behavior in the future, what, if anything beyond what I've done, might I do to fix it?
推荐答案
这通常是在头文件中定义对象的结果,而不是仅仅声明它.考虑:
This is often the result of defining an object in a header file, rather than merely declaring it. Consider:
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;
.
This will produce a duplicate symbol i
. The solution is to declare the object in the header file: extern int i;
and to define it in exactly one of the source-code files: int i;
.
相关文章