C++ 了解链接器重复符号错误的起源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6116188/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:30:59  来源:igfitidea点击:

Understanding the origin of a linker duplicate symbol error

c++gcclinkerclang

提问by rcollyer

I have a c++ program that compiled previously, but after mucking with the Jamfiles, the program no longer compiled and ldemitted 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.

我有一个以前编译过的 c++ 程序,但是在使用 Jamfiles 之后,该程序不再编译并ld发出duplicate symbol error. 在连续恢复到原始 Jamfiles、运行bjam clean、手动删除对象以及从带有 gcc 前端的 clang 切换到 MacOs 10.6.7 上的 gcc 4.2.1之后,这种情况仍然存在。

A simplified description of the program is that there is main.cppand four files, a.h,cppand b.h,cpp, which are compiled into a static library which is linked to main.o. Both, main.cppand b.cppdepend on the file containing the offending symbol, off.h, through two different intermediate files, but neither a.hnor a.cppdepend in any way on off.h.

该程序的一个简化描述是有main.cpp四个文件a.h,cppb.h,cpp,它们被编译成一个链接到main.o. 两者,main.cpp并且b.cpp取决于包含冒犯符号的文件off.h,通过两个不同的中间文件,但既不a.h也不a.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.hdoes not include anything that references off.h, only the implementation, b.cpp, makes any reference to off.h. This alone had me puzzled.

在您询问之前,我确保所有文件都包含在多个定义保护 ( #ifndef, #define, #endif) 中,虽然我确实找到了缺少它们的文件,但它没有引用off.h. 更重要的是,b.h不包括任何引用off.h,只有实现,b.cpp,对 进行任何引用off.h。仅此一点就让我感到困惑。

To add to my confusion, I was able to remove the reference to off.hfrom b.cppand, 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.

更让我困惑的是,我能够删除对off.hfrom的引用,b.cpp并且正如预期的那样,它重新编译成功。但是,当我重新添加引用时,它也编译成功,并在清除目标文件后继续编译。我仍然不知道为什么它无法编译,特别是考虑到符号不应该发生冲突,我已经防止了符号重复,并且我已经摆脱了任何先前/不完整的构建。

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?

由于我能够成功编译我的程序,我怀疑我是否能够重现它以测试任何建议。但是,我很好奇这是如何发生的,如果我将来遇到这种行为,如果超出我所做的任何事情,我可以做些什么来解决它?

回答by Rob?

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:

a.cpp:

#include "h.h"

b.cpp:

b.cpp:

#include "h.h"
int main() {}

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;.

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