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

2022-01-11 00:00:00 gcc clang linker c++

我有一个以前编译过的 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,cppbh,cpp,分别是被编译成一个链接到 main.o 的静态库.main.cppb.cpp 都通过两个不同的中间文件依赖于包含违规符号 off.h 的文件,但是aha.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;.

相关文章