C++ 找到一个或多个多重定义的符号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6469849/
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
One or more multiply defined symbols found
提问by Tiago Costa
DebugUtil.h
调试工具
#ifndef DEBUG_UTIL_H
#define DEBUG_UTIL_H
#include <windows.h>
int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
#endif
When I try to run this I get this error:
当我尝试运行它时,我收到此错误:
Terrain.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" (?DebugMessage@@YAHPBD@Z) already defined in Loodus.obj
Renderer.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" (?DebugMessage@@YAHPBD@Z) already defined in Loodus.obj
test.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" (?DebugMessage@@YAHPBD@Z) already defined in Loodus.obj
C:\Users\Tiago\Desktop\Loodus Engine\Debug\Loodus Engine.exe : fatal error LNK1169: one or more multiply defined symbols found
Terrain.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" (?DebugMessage@@YAHPBD@Z) 已经在 Loodus.obj 中定义
Renderer.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" (?DebugMessage@@YAHPBD@Z) 已经在 Loodus.obj 中定义
test.obj : error LNK2005: "int __cdecl DebugMessage(char const *)" (?DebugMessage@@YAHPBD@Z) 已经在 Loodus.obj 中定义
C:\Users\Tiago\Desktop\Loodus Engine\Debug\Loodus Engine.exe:致命错误 LNK1169:发现一个或多个多重定义的符号
But why does this happen? I have #ifndef #define and #endif in the header so multiple definitions shouldn't happen
但为什么会发生这种情况?我在标题中有 #ifndef #define 和 #endif,因此不应发生多个定义
回答by Armen Tsirunyan
Put the definition (body) in a cpp file and leave only the declaration in a h file. Include guards operate only within one translation unit (aka source file), not across all your program.
将定义(主体)放在 cpp 文件中,只在 ah 文件中保留声明。包含守卫只在一个翻译单元(也就是源文件)中运行,而不是在你的所有程序中运行。
The One Definition Rule of the C++ standard states that there shall appear exactly one definition of each non-inline function that is used in the program. So, another alternative would be to make your function inline.
C++ 标准的一个定义规则规定,程序中使用的每个非内联函数都应该出现一个定义。因此,另一种选择是使您的函数内联。
回答by GWW
Make the function inline or declare the function in a header file and define it in a cpp file.
使函数内联或在头文件中声明函数并在 cpp 文件中定义它。
inline int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
EDIT:
编辑:
As a comment by Tomalak Geret'kal suggests, it's better to use my latter suggestions than my former and move the function's declaration to a cpp file.
正如 Tomalak Geret'kal 的评论所建议的那样,最好使用我的后一个建议而不是我的前一个并将函数的声明移动到 cpp 文件。
回答by Lightness Races in Orbit
(Assuming the posted code is a header, included from multiple .cpp files)
(假设发布的代码是一个标题,包含在多个 .cpp 文件中)
Header guards do not protect you from link-time multiple definitions. Regardless that you have ensured the header will only appear once per Translation Unit, if you have more than one Translation Unit then that's still multiple definitions.
标头保护不能保护您免受链接时多重定义的影响。不管您是否确保标题在每个翻译单元中只出现一次,如果您有多个翻译单元,那么这仍然是多个定义。
Write definitions in source files, and only declarationsin headers.
在源文件中写入定义,仅在头文件中写入声明。
The only exceptions are inline
functions, functions defined within a class
definition (though this is not recommended!) and function templates.
唯一的例外是inline
函数、在class
定义中定义的函数(尽管不推荐这样做!)和函数模板。
回答by Assaf Lavie
This function is included into every translation unit and as a result you get multiple definitions of it - each .obj file contains its own copy. When it's time to link them all together the linker rightfully shows the above error.
此函数包含在每个翻译单元中,因此您会得到它的多个定义 - 每个 .obj 文件都包含自己的副本。当需要将它们全部链接在一起时,链接器正确地显示了上述错误。
You can do a few things:
你可以做几件事:
- Move the definition to a .cpp file and keep only the declaration in the header.
- Use an anonymous namespace around the function in your header file (but realize it's a hack - you will still have multiple definitions, just no name collision).
- Mark it as inline (although it might not always work - only if the compiler actually chooses to inline it). That's also a hack for the same reason as above.
- 将定义移动到 .cpp 文件并仅保留标题中的声明。
- 在头文件中的函数周围使用匿名命名空间(但要意识到这是一个黑客 - 您仍然会有多个定义,只是没有名称冲突)。
- 将其标记为内联(尽管它可能并不总是有效 - 仅当编译器实际选择内联它时)。出于与上述相同的原因,这也是一种黑客攻击。
回答by J.M.I. MADISON
100% Certain you correctly included Guards but still getting redefinition error?
100% 确定您正确地包含了 Guards 但仍然出现重新定义错误?
For Visual Studio:I was really frustrated because I was correctly included guards, only to find out the problem was visual studio. If you have added the file to your project, the compiler will add the file twice even if you have include guards around your implementation file and header file.
对于 Visual Studio:我真的很沮丧,因为我正确地包含了守卫,结果发现问题出在 Visual Studio。如果您已将该文件添加到您的项目中,即使您在实现文件和头文件周围有包含保护,编译器也会将该文件添加两次。
If you don't use visual studio exclusively, and say... use code::blocks sometimes, you might want to only #include the file when you detect the absence of the visual studio environment.
如果您不专门使用 Visual Studio,并且说...有时使用 code::blocks,当您检测到不存在 Visual Studio 环境时,您可能只想 #include 文件。
DebugUtil.h :
----------------------
#ifndef _WIN32
#include "DebugUtil.c"
#endif
----------------------
If you are okay with including stdio.h, you can be a little less hackish about it:
如果您同意包含 stdio.h,那么您就可以少一些黑客攻击:
DebugUtil.h :
----------------------
#include <stdio.h>
#ifdef _MSC_VER
#include "DebugUtil.c"
#endif
----------------------
Reference: Predefined Macros, Visual Studio: https://msdn.microsoft.com/en-us/library/b0084kay.aspx
参考:预定义宏,Visual Studio:https: //msdn.microsoft.com/en-us/library/b0084kay.aspx
回答by MGZero
Move the definition to a .cpp file.
将定义移动到 .cpp 文件。
回答by Jonathan Wood
Declare your functions in C++ files. Since you defined your function in the header file, and that header file is included from multiple source files, it gets defined for each source file that includes it. That's why it's reported as being defined in multiple places.
在 C++ 文件中声明您的函数。由于您在头文件中定义了函数,并且该头文件包含在多个源文件中,因此它为包含它的每个源文件定义。这就是为什么它被报告为在多个地方定义的原因。
Alternatively, you could make it inline so that the code is inserted wherever it's used instead of being defined as a separate function each time.
或者,您可以将其设置为内联,以便将代码插入到使用它的任何位置,而不是每次都定义为一个单独的函数。
回答by acm
It looks like you are including DebugUtil.h in more than one translation unit, then linking those objects together. However, DebugUtil.h provides a definition for the DebugMessage function, so that definition exists in all of the translation units that incorporated the header. As a result, when you link the objects, the linker rightly complains that the symbol is multiply defined.
看起来您在多个翻译单元中包含 DebugUtil.h,然后将这些对象链接在一起。但是,DebugUtil.h 提供了 DebugMessage 函数的定义,因此该定义存在于包含标头的所有翻译单元中。结果,当您链接对象时,链接器正确地抱怨符号是多重定义的。
Change DebugUtil.h so that it declares DebugMessage via a prototype, but does not provide a definition, and place the definition of DebugMessage in a .c file which you will compile and link with your other objects.
更改 DebugUtil.h 使其通过原型声明 DebugMessage,但不提供定义,并将 DebugMessage 的定义放置在您将编译并与其他对象链接的 .c 文件中。
回答by geekosaur
That only prevents multiple inclusions in the same source file; multiple source files #include
ing it will still generate multiple definitions of DebugMessage()
. In general, you should either not place functions in header files at all or make them static
(and usually inline
, since otherwise it doesn't usually make sense to have multiple static
definitions of the same function).
这只会防止在同一个源文件中包含多个内容;多个源文件#include
ing 它仍然会生成DebugMessage()
. 通常,您要么根本不将函数放在头文件中,要么创建它们static
(通常是inline
,否则通常static
对同一函数有多个定义没有意义)。