Reputation: 3703
I have 2 files, A.cpp and B.cpp, in a Win32 console application.
Both 2 files contain only the following 2 lines of code:
#include "stdafx.h"
int k;
When compiling it produces the error
Error 1 error LNK2005: "int k" (?a@@3HA) already defined in A.obj
I don't understand what is happening.
Can someone please explain this to me?
Upvotes: 82
Views: 253113
Reputation: 123
As mentioned before from the community, this is caused basically by implementing the definition in a header file and include it several times in the project. to solve the issue I used the inline in before the definition of variables and functions/methods and it is working fine.
//in the header file:
inline int k{123};
Upvotes: 0
Reputation: 4225
In the Project’s Settings, add /FORCE:MULTIPLE
to the Linker’s Command Line options.
From MSDN: "Use /FORCE:MULTIPLE to create an output file whether or not LINK finds more than one definition for a symbol."
Upvotes: 91
Reputation: 37549
Presence of int k;
in the header file causes symbol k
to be defined within each translation unit this header is included to while linker expects it to be defined only once (aka One Definition Rule Violation).
While suggestion involving extern
are not wrong, extern
is a C-ism and should not be used.
Pre C++17 solution that would allow variable in header file to be defined in multiple translation units without causing ODR violation would be conversion to template:
template<typename x_Dummy = void> class
t_HeaderVariableHolder
{
public: static int s_k;
};
template<typename x_Dummy> int t_HeaderVariableHolder<x_Dummy>::s_k{};
// Getter is necessary to decouple variable storage implementation details from access to it.
inline int & Get_K() noexcept
{
return t_HeaderVariableHolder<>::s_k;
}
With C++17 things become much simpler as it allows inline
variables:
inline int g_k{};
// Getter is necessary to decouple variable storage implementation details from access to it.
inline int & Get_K() noexcept
{
return g_k;
}
Upvotes: 3
Reputation: 490118
If you want both to reference the same variable, one of them should have int k;
, and the other should have extern int k;
For this situation, you typically put the definition (int k;
) in one .cpp
file, and put the declaration (extern int k;
) in a header, to be included wherever you need access to that variable.
If you want each k
to be a separate variable that just happen to have the same name, you can either mark them as static
, like: static int k;
(in all files, or at least all but one file). Alternatively, you can us an anonymous namespace:
namespace {
int k;
};
Again, in all but at most one of the files.
In C, the compiler generally isn't quite so picky about this. Specifically, C has a concept of a "tentative definition", so if you have something like int k;
twice (in either the same or separate source files) each will be treated as a tentative definition, and there won't be a conflict between them. This can be a bit confusing, however, because you still can't have two definitions that both include initializers--a definition with an initializer is always a full definition, not a tentative definition. In other words, int k = 1;
appearing twice would be an error, but int k;
in one place and int k = 1;
in another would not. In this case, the int k;
would be treated as a tentative definition and the int k = 1;
as a definition (and both refer to the same variable).
Upvotes: 15
Reputation: 206526
Why this error?
You broke the one definition rule and hence the linking error.
Suggested Solutions:
If you need the same named variable in the two cpp files then You need to use Nameless namespace(Anonymous Namespace) to avoid the error.
namespace
{
int k;
}
If you need to share the same variable across multiple files then you need to use extern
.
A.h
extern int k;
A.cpp
#include "A.h"
int k = 0;
B.cpp
#include "A.h"
//Use `k` anywhere in the file
Upvotes: 112
Reputation: 28762
The linker tells you that you have the variable k
defined multiple times. Indeed, you have a definition in A.cpp and another in B.cpp. Both compilation units produce a corresponding object file that the linker uses to create your program. The problem is that in your case the linker does not know whic definition of k
to use. In C++ you can have only one defintion of the same construct (variable, type, function).
To fix it, you will have to decide what your goal is
k
, you can use an anonymous namespace in both .cpp files, then refer to k
as you are doing now:.
namespace {
int k;
}
k
s to something else, thus avoiding the duplicate defintion.k
and use that in both .cpp files, you need to declare in one as extern int k;
, and leave it as it is in the other. This will tell the linker to use the one definition (the unchanged version) in both cases -- extern
implies that the variable is defined in another compilation unit.Upvotes: 1
Reputation: 64682
Both files define variable k
as an integer (int
).
As a result, the linker sees two variables with the same name, and is unsure which one it should use if you ever refer to k
.
To fix this, change one of the declarations to:
extern int k;
That means: "k is an integer, declared here, but defined externally (ie. the other file)."
Now there is only one variable k
, that can be properly referred to by two different files.
Upvotes: 6
Reputation: 34401
And if you want these translation units to share this variable, define int k;
in A.cpp and put extern int k;
in B.cpp.
Upvotes: 4
Reputation: 6957
Assuming you want 'k' to be a different value in different .cpp files (hence declaring it twice), try changing both files to
namespace {
int k;
}
This guarantees that the name 'k' uniquely identifies 'k' across translation units. The old version static int k;
is deprecated.
If you want them to point to the same value, change one to extern int k;
.
Upvotes: 6