81

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?

dandan78
  • 13,328
  • 13
  • 64
  • 78
TTGroup
  • 3,575
  • 10
  • 47
  • 79
  • 11
    T&T Group? Is that your company name? I would not recommend signing off with your company's name when you ask basic questions. Especially if your customers expect you to protect their information of some sort. – CodyBugstein Jan 26 '14 at 13:45
  • 2
    **Hint for fellas:** a missing `#include "stdafx.h"` is the source for this error, too. – Bitterblue May 19 '14 at 10:24
  • I had this error while compiling a CMake project in visual studio and making edits outside the IDE. It was eventually fixed by cleaning the build folder. – MHebes Feb 27 '23 at 22:01

8 Answers8

111

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 
Alok Save
  • 202,538
  • 53
  • 430
  • 533
87

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

Michael Haephrati
  • 3,660
  • 1
  • 33
  • 56
  • 6
    This is the **only** solution when the linker or preprocessor fail to see that that thing is only defined **once**! Must be also some bug in VS. I just wonder how did it work for so long for so many people. (I'm not referring to the Q here but to my linker errors that are from outa space, I guess ...) – Bitterblue May 19 '14 at 09:58
  • 8
    I have a feeling that this is a 'brute-force' way of doing this and doesn't actually solve the original problem; it made half my functions point to nulls. As this solved my issue, I'm giving this answer +1. – AStopher Nov 08 '14 at 18:37
  • 1
    Want to point out that this may be the only way to solve it if you are compiling with new compiler the codebase which uses old compiled static libraries. – Predelnik Mar 19 '15 at 19:17
  • This worked for a slightly different link problem that I had with the C Runtime Libraries. I was getting duplicate static resolutions of math library functions in multiple object files. – ergohack Jul 06 '16 at 20:41
  • 2
    While this answer isn't the correct answer for the OP's question, I'm upvoting because this works for me. I'm getting this error because I'm including a header file for the module I'm writing unit tests for, which in turn includes wx/string.h (but my unit tests don't use wxString). The unit tests compile as a separate project, thus wxString::~wxString gets defined in two .obj files. This solution allows me to continue writing unit tests without having to completely refactor the code I'm maintaining (which needs refactoring, but that's going to take some time). – hlongmore Sep 14 '16 at 22:18
  • One of the libraries i was using throwing the linker errors and changing it was too tedious. This solved the problem. – Plutonium smuggler Jul 02 '19 at 05:10
  • I am glad to hear! Thank you! – Michael Haephrati Jul 02 '19 at 19:02
  • This is available in **Project Properties > Linker > All Options > Force File Output** – DLT Apr 24 '23 at 04:47
15

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

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • +1 but jerry, it would be nice if you would add some words about C. i think maybe the OP is coming from C, with its "tentative" declarations... the C/C++ difference confused me for a log time. – Cheers and hth. - Alf Apr 06 '12 at 16:56
  • 1
    The static keyword helped me when I defined the variable only once. Thanks! – Pete Dec 03 '14 at 06:37
6

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

Steve Howard
  • 6,737
  • 1
  • 26
  • 37
6

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.

abelenky
  • 63,815
  • 23
  • 109
  • 159
3

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.

arrowd
  • 33,231
  • 8
  • 79
  • 110
3

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;
}
user7860670
  • 35,849
  • 4
  • 58
  • 84
  • What is this? Where is the normal variable in the header file I expected to see? What is `{}` after `g_k` ? How can I set a global variable with a value in the header file without ODR violation? – gil123 Apr 12 '19 at 21:16
  • @gil123 `{}` is [list initialization syntax](https://en.cppreference.com/w/cpp/language/list_initialization). Empty list will initialize int with 0 while some initial value can be provided as well like `inline int g_k{1234};`. There will be no ODR violations because of the way linker handles templates and inline variables. In this case linker will select just one definition to form the resulting program instead of complaining about it being already defined somewhere else. – user7860670 Apr 12 '19 at 21:22
  • It took so much time for C++ to allow something that is so much basic in a simple way - allow global variables **with values** in headers file. It is so wired that it was not allowed before in a simple way. the thing that did the trick is the `inline` keyword. I still did not understand why you did not just write `inline int g_k = 0;` ? I noticed that this syntax will initialize the variable with the value `0`. Why do you use list syntax to set only one value? Why it is a better way than use the `=` operator? – gil123 Apr 12 '19 at 22:08
1

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

  • If you want to have two variables, both named k, you can use an anonymous namespace in both .cpp files, then refer to k as you are doing now:

.

namespace {
  int k;
}
  • You can rename one of the ks to something else, thus avoiding the duplicate defintion.
  • If you want to have only once definition of 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.
Attila
  • 28,265
  • 3
  • 46
  • 55