了解链接器的原点重复符号错误
我有一个以前编译的c ++程序,但是在使用Jamfiles之后,程序不再编译并且 ld
发出了一个重复的符号错误
。这种情况持续发生在之后恢复到原始的Jamfiles,运行 bjam clean
,手动删除对象,并从gcc前端切换到gcc 4.2.1 .7。
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
,引用 off.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.
要添加我的混淆,我可以从 off.h 的引用c> b.cpp ,并且如预期的那样重新编译成功。但是,当我添加参考回来,它也编译成功,并继续这样做后清理出目标文件。我仍然失去了为什么它没有编译,特别是考虑到符号不应该冲突,我已经防止了符号重复,我已经摆脱了任何先前/不完整的构建。
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:
hh :
#ifndef H_H_
#define H_H_
int i;
#endif
a.cpp :
#include "h.h"
$ b b
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;
.