Visual Studio error LNK2005: variable XXX redefined in xxx.obj
-
I tried to isolate the problem It appears when a global variable is declared at the .h header file and the header file is called from 2 or more cpp files, as example I tried to link the following 3 files:
//==File: header.h
#pragma once
#include int variable;
//==end header.h//==File: main.cpp
#include "header.h"
void main()
{
variable=0;
}
//==end main.h//File: source2.cpp
#include "header.h"void change()
{
variable=0;
}
//==end source2.cppThen the following LINKER error appear: 1>source2.obj : error LNK2005: redefined "int variable" (?variable@@3HA) in main.obj The only way I could "fix" the problem is in project properties> linker>command line add: /FORCE:MULTIPLE Unfortunately it can hide possible problems I think the problem is that the #pragma once does not work. It does not work also to define a constant and use #ifndef to avoid reading 2 times.
Another way to solve this problem (and have only one place where the variable is defined): In foo.h:
#ifdef DEFINE_GLOBALS
#define GLOBAL
#define INIT(x) = (x)
#else
#define GLOBAL extern
#define INIT(x)
#endifGLOBAL int globalInt INIT(42);
In foo.cpp (and ONLY in foo.cpp):
#define DEFINE_GLOBALS
#include "foo.h"In other source files:
#include "foo.h"
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack. --Winston Churchill
-
Another way to solve this problem (and have only one place where the variable is defined): In foo.h:
#ifdef DEFINE_GLOBALS
#define GLOBAL
#define INIT(x) = (x)
#else
#define GLOBAL extern
#define INIT(x)
#endifGLOBAL int globalInt INIT(42);
In foo.cpp (and ONLY in foo.cpp):
#define DEFINE_GLOBALS
#include "foo.h"In other source files:
#include "foo.h"
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack. --Winston Churchill
-
Another way to solve this problem (and have only one place where the variable is defined): In foo.h:
#ifdef DEFINE_GLOBALS
#define GLOBAL
#define INIT(x) = (x)
#else
#define GLOBAL extern
#define INIT(x)
#endifGLOBAL int globalInt INIT(42);
In foo.cpp (and ONLY in foo.cpp):
#define DEFINE_GLOBALS
#include "foo.h"In other source files:
#include "foo.h"
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack. --Winston Churchill
-
The problem with this is that everything is hidden by those
#define
s so as to make it less easy to understand when looking at the source code.It can be confusing if encountered for the first time, but if this is the agreed idiom in your team, it ensures that all definitions occur only once. This in turn eliminates all possibilities of mismatches between declarations and definitions.
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack. --Winston Churchill
-
I tried to isolate the problem It appears when a global variable is declared at the .h header file and the header file is called from 2 or more cpp files, as example I tried to link the following 3 files:
//==File: header.h
#pragma once
#include int variable;
//==end header.h//==File: main.cpp
#include "header.h"
void main()
{
variable=0;
}
//==end main.h//File: source2.cpp
#include "header.h"void change()
{
variable=0;
}
//==end source2.cppThen the following LINKER error appear: 1>source2.obj : error LNK2005: redefined "int variable" (?variable@@3HA) in main.obj The only way I could "fix" the problem is in project properties> linker>command line add: /FORCE:MULTIPLE Unfortunately it can hide possible problems I think the problem is that the #pragma once does not work. It does not work also to define a constant and use #ifndef to avoid reading 2 times.
The basis for the error is that building an EXE constitutes compiling and linking. Compilation - Every CPP file, also called a translation unit or compilation unit, is compiled separately to form OBJ files. Linking - All the OBJ files are linked together to become the EXE. In your case, during compilation, every OBJ file will contain a symbol called
int variable
. This means the compilation of all units are successful. But when the linker takes all the OBJ files to create an EXE, it finds the same symbol in all translation units and so it becomes ambiguous to it as to which symbol to use. Having said this, there are two things that you may want to do with global variables. First You may want to use a global variable that is shared between all translation units. This is the answer that you've gotten so far. The global variable declaration must happen only once so that the linker only finds one symbol for the variable and links all otherextern
references to that symbol. Second You may want to use the same name for the global variable in each translation unit. For this to happen, declare the global variable as static -static int variable;
This forces the compilation process to not share the symbol among other translation units. For more information refer to this link - Types of Linkage[^]«_Superman_» _I love work. It gives me something to do between weekends.
_Microsoft MVP (Visual C++) (October 2009 - September 2013)
-
The basis for the error is that building an EXE constitutes compiling and linking. Compilation - Every CPP file, also called a translation unit or compilation unit, is compiled separately to form OBJ files. Linking - All the OBJ files are linked together to become the EXE. In your case, during compilation, every OBJ file will contain a symbol called
int variable
. This means the compilation of all units are successful. But when the linker takes all the OBJ files to create an EXE, it finds the same symbol in all translation units and so it becomes ambiguous to it as to which symbol to use. Having said this, there are two things that you may want to do with global variables. First You may want to use a global variable that is shared between all translation units. This is the answer that you've gotten so far. The global variable declaration must happen only once so that the linker only finds one symbol for the variable and links all otherextern
references to that symbol. Second You may want to use the same name for the global variable in each translation unit. For this to happen, declare the global variable as static -static int variable;
This forces the compilation process to not share the symbol among other translation units. For more information refer to this link - Types of Linkage[^]«_Superman_» _I love work. It gives me something to do between weekends.
_Microsoft MVP (Visual C++) (October 2009 - September 2013)
-
«_Superman_» wrote:
For this to happen, declare the global variable as static -
static int variable;
Which means they are not global.
They are definitely not local. They are global to the functions in that file. They are local to that file. If you look at the assembly output, they are created as global variables.
«_Superman_» _I love work. It gives me something to do between weekends.
_Microsoft MVP (Visual C++) (October 2009 - September 2013)
-
They are definitely not local. They are global to the functions in that file. They are local to that file. If you look at the assembly output, they are created as global variables.
«_Superman_» _I love work. It gives me something to do between weekends.
_Microsoft MVP (Visual C++) (October 2009 - September 2013)
«_Superman_» wrote:
They are definitely not local.
Yes they are; go back to the link in your original post and read it again.
«_Superman_» wrote:
They are global to the functions in that file.
The term 'global' here is confusing the issue.
«_Superman_» wrote:
They are local to that file.
So which is it?
«_Superman_» wrote:
If you look at the assembly output, they are created as global variables.
Again you misunderstand the term 'global'.
-
«_Superman_» wrote:
They are definitely not local.
Yes they are; go back to the link in your original post and read it again.
«_Superman_» wrote:
They are global to the functions in that file.
The term 'global' here is confusing the issue.
«_Superman_» wrote:
They are local to that file.
So which is it?
«_Superman_» wrote:
If you look at the assembly output, they are created as global variables.
Again you misunderstand the term 'global'.
It is a global variable with file scope.
«_Superman_» _I love work. It gives me something to do between weekends.
_Microsoft MVP (Visual C++) (October 2009 - September 2013)
-
It is a global variable with file scope.
«_Superman_» _I love work. It gives me something to do between weekends.
_Microsoft MVP (Visual C++) (October 2009 - September 2013)