In a big project, I have a .h file which defines a lot of constants within a namespace. Introducing const char* constants results in linker errors complaining of multiple definitions.
ex.h
#include <string>
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char* NAME2 = "fred"; // <-- ERROR: multiple definition of `Dv::NAME2'
}
exA.cpp
#include "ex.h"
void aFunction() { printf("this is aFunction\n"); }
exB.cpp
#include "ex.h"
void aFunction(void);
int main(int argc, char **argv)
{
aFunction();
return 0;
}
Compile and Link
g++ -c exA.cpp
g++ -c exB.cpp
g++ exA.o exB.o -o ex
exB.o:(.data+0x0): multiple definition of `Dv::NAME2'
exA.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
The linker error happens if NAME2 is included in the .h file. Why?
If MAX is also a POD (like char[]?), why does the linker not complain of multiple int MAX definitions? (or multiple std::string NAME definitions for that matter?)
I don't understand what's special about char[] in this situation.
Thanks
According to the C++ Standard (3.5 Program and linkage)
3 A name having namespace scope (3.3.6) has internal linkage if it is
the name of
— a non-volatile variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously
declared to have external linkage; or
and
4 An unnamed namespace or a namespace declared directly or indirectly
within an unnamed namespace has internal linkage. All other
namespaces have external linkage. A name having namespace scope that
has not been given internal linkage above has the same linkage as the
enclosing namespace if it is the name of — a variable; or
In this namespace definition
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char* NAME2 = "fred"; // <-- ERROR: multiple definition of `Dv::NAME2'
}
(the only) variable NAME2 is not a constant and hence has external linkage.
You could make it as having internal linkage defining it for example with keyword static. For example
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
static const char* NAME2 = "fred";
}
Or could define it as a constant
namespace Dv
{
const int MAX = 10;
const std::string NAME = "bobo";
const char * const NAME2 = "fred";
}
Related
I know that this subject has already been discussed on this site, I tested the solutions but it doesn't work, I always have the same mistake. Please help me :')
Player.cpp
#include "Player.hpp"
namespace Player
{
const char *name = "Jason";
}
Card.cpp
#include "Player.hpp"
namespace Player
{
const char *name = "Jason";
}
Player.hpp
namespace Player
{
extern const char *name;
}
You can have at most one definition of each unique fully-qualified symbol in your program. The linker error you are receiving is occurring because you provide a definition for the symbol Player::name in both Player.cpp and Card.cpp.
You are free to reuse variable names; but the symbol must still be unique to avoid these issues. For your particular problem, this may be solved through one of the following:
Defining the symbol in a different namespace
For example, you could change Card.cpp to be:
// Symbol is Card::name -- which is different from Player::card
namespace Card {
const char* name = ...;
} // namespace
Defining the symbol as a static member of a struct/class
This could be something like:
// Symbol is Player::Card::name -- which is different from Player::card
namespace Player {
struct Card {
static const char* name = ...;
};
}
Marking the symbol with internal linkage
This could be done using an unnamed namespace (C++11 and above), or static (older C++):
// Symbol is Player::<some unique name>::name
namespace Player {
namespace {
const char* name = ...;
}
// or 'static const char* name = ...;'
}
note: This method, unlike the others, cannot be used across different source files. The symbol is "internalized", which means it is unique to the one compilation unit (source file).
I want to avoid #defines in my code. Accordingly, I have the following in a header file :
#ifndef __GATENAMES__
#define __GATENAMES__
namespace GateNames
{
const char* CBSD_GATE_TO_SAS = "CbsdGate_SAS_INOUT";
const char* CBSD_GATE_TO_SAS_OUT = "CbsdGate_SAS_INOUT$o";
const char* CBSD_GATE_TO_SAS_IN = "CbsdGate_SAS_INOUT$i";
const char* SAS_GATE_TO_CBSD = "SasGate_CBSD_INOUT";
const char* SAS_GATE_TO_ESC = "SasGate_ESC_INOUT";
const char* SAS_GATE_TO_ESC_OUT = "SasGate_ESC_INOUT$o";
const char* SAS_GATE_TO_ESC_IN = "SasGate_ESC_INOUT$i";
};
#endif
This header file is included in various places in my code. However, the linker complains that the symbols are multiply defined:
../out/gcc-debug/src/CbsdSim.o:(.data.rel.local+0x0): multiple definition of `GateNames::CBSD_GATE_TO_SAS'
How can I get around this problem? Thanks.
Firstly, names like this __GATENAMES__, (any name starting with an underscore and an uppercase letter or containing two consecutive underscores) is reserved for the C++ implementation - you shgould not be creating such names in your own code.
Secondly, your constness is a bit mixed up, instead of things like:
const char* CBSD_GATE_TO_SAS = "CbsdGate_SAS_INOUT";
you want:
const char * const CBSD_GATE_TO_SAS = "CbsdGate_SAS_INOUT";
In other words, it's the pointer that's got to be const to limit the linkage of the pointer, not the thing pointed to (although in this case that also has to be const).
The reason for your linker errors is that non const variables have external linkage, and since you defined them in multiple translation units (by including a header), linker complains.
There are three ways to fix your code. First is to change linkage of your const char* string literals, by making them static. This way they have internal linkage, and each translation unit which includes them will not share them with other translation units - so also linker will not complain:
static const char* CBSD_GATE_TO_SAS = "CbsdGate_SAS_INOUT";
^^^^^^
Second one is to make them const:
const char* const CBSD_GATE_TO_SAS = "CbsdGate_SAS_INOUT";
^^^^^
which is actually quite similar to making them static, they have now internal linkage.
Third way is to declare them in header file and define in one single translation unit.:
// in header file
namespace GateNames
{
extern const char* CBSD_GATE_TO_SAS ;
};
in some .cpp file:
namespace GateNames
{
const char* CBSD_GATE_TO_SAS = "CbsdGate_SAS_INOUT";
};
Could someone please advise?
If const in C++ defaults to internal linkage, why do I get multiple definition errors in the code below?
First, the file dem.h:
#ifndef _DEM_H_
#define _DEM_H_
class Dem {
public:
static const int i;
};
const int Dem::i = 10;
#endif
Them imp1.cpp:
#include "dem.h"
#include <iostream>
using namespace std;
extern int foo();
int main() {
cout << foo() << endl;
}
and imp2.cpp:
#include "dem.h"
int foo() {
return Dem::i ;
}
I compile with the following command and results:
$ g++ imp1.cpp imp2.cpp
/tmp/ccmGt0OY.o:imp2.cpp:(.rdata+0x0): multiple definition of `Dem::i'
/tmp/cc5sN7dz.o:imp1.cpp:(.rdata+0x0): first defined here
collect2: ld returned 1 exit status
From C++11 [basic.link], paragraph 5:
In addition, a member function, static data member, a named class or enumeration of class scope, or an unnamed class or enumeration defined in a class-scope typedef declaration such that the class or enumeration has the typedef name for linkage purposes (7.1.3), has external linkage if the name of the class has external linkage.
Because your class has external linkage, so does your static data member.
Its static to the compilation unit. You are compiling in two steps - first impl1.cpp and then impl2.cpp - and in each unit the compiler instantiates the static data member. When the linker then tries to link the two associated object files together, it sees two different definitions for the same symbol , and so you get a multiple definition error.
I would like to define array of strings in different cpp file, but there seems to be some discrepancy between definition and declaration when I try to make pointer (array element) also const. Using the same definition as declaration seems to work fine, so I suspect initialization is not an issue. In the code below I have commented out offending const - so it will compile, but if const is un-commented, linker (tested with g++ 4.6 & VS10) will not find ext_string_array.
main.cpp:
#include <iostream>
const char* const string_array[2] =
{
"aaa",
"bbb"
};
extern const char* /*const*/ ext_string_array[2]; // <- offending const
int main()
{
std::cout << string_array[0];
std::cout << ext_string_array[0];
}
definition.cpp:
const char* /*const*/ ext_string_array[2] = // <- offending const
{
"aaa",
"bbb"
};
In this context const also means static, unless you also specify extern. Change your .cpp file to this
extern const char* const ext_string_array[2] =
{
"aaa",
"bbb"
};
C++ 2003, 3.5 Program and Linkage, 3:
A name having namespace scope (3.3.5) has internal linkage if it is the name of
[...]
— an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage; [...]
So you need an explicit extern in the declaration..
I was told that these types, that are visible in there own unique translation unit, were in violation of the One Definition Rule. Can someone explain this?
//File1.cpp
#include "StdAfx.h"
static struct S { int Value() { return 1; } } s1;
int GetValue1() { return s1.Value(); }
//File2.cpp
#include "StdAfx.h"
static struct S { int Value() { return 2; } } s2;
int GetValue2() { return s2.Value(); }
// main.cpp
#include "stdafx.h"
extern int GetValue1();
extern int GetValue2();
int _tmain(int argc, _TCHAR* argv[])
{
if( GetValue1() != 1 ) throw "ODR violation";
if( GetValue2() != 2 ) throw "ODR violation";
return 0;
}
I know how to fix the problem. As per the title, I was looking to why it was a ODR violation. How does it violate: "In any translation unit, a template, type, function, or object can have no more than one definition."? Or maybe it violates a different part of the rule.
The problem is that, even though s1 and s2 have only internal linkage, both of the corresponding definitions of S have external linkage.
What you want to do is to use an anonymous namespace:
//File1.cpp
#include "StdAfx.h"
namespace {
struct S { int Value() { return 1; } } s1;
}
int GetValue1() { return s1.Value(); }
//File2.cpp
#include "StdAfx.h"
namespace {
struct S { int Value() { return 2; } } s2;
}
int GetValue2() { return s2.Value(); }
Edit:
Everything inside the anonymous namespace, including the class definitions, has internal linkage.
Definitions in the anonymous namespace still have external linkage, but the compiler ensures that they receive unique names that won't clash with any definitions from other translation units.
This is unsafe because you have two structs named S. The static keyword only applies to the variable declaration; it's equivalent to you having written:
struct S {
int Value() {return 1;}
};
static S s1;
The compiler doesn't notice this at compile time because it deals with each translation unit separately. The Value functions in the structs are mangled to exactly the same name, and become weak global symbols in the object files, so the linker doesn't throw an error about a symbol name collision; it just picks one to use in the fully-linked binary. This will probably be the first symbol definition, which means you can actually get different behavior depending on the order you linked the objects:
> g++ -o test test.o test1.o test2.o && ./test
s1 is 1
s2 is 1
> g++ -o test test.o test2.o test1.o && ./test
s1 is 2
s2 is 2
You can get around this by either wrapping the structs in anonymous namespaces (which will make the Value function symbols locals instead of weak globals):
namespace {
struct S {
int Value() {return 1;}
} s1;
}
Or simply removing the name of the struct, since you don't actually need it:
struct {
int Value() {return 1;}
} s1;
You have defined struct S in the global namespace in two different ways, which breaks the One Definition Rule. In particular, there are two different definitions of ::S::Value(), and it's undefined which will actually end up being called.
You should use nameless namespaces to make sure a distinctly named version of struct S is defined in each translation unit:
namespace { struct S {int Value() {return 1;}} s1; }
int GetValue1() {return s1.Value();}
There's a lot more to the One Definition Rule than the first paragraph which you quote. The last paragraph basically says that some things, including class definitions, can appear more than once in a program, as long as they are all identical. Your code breaks this last condition. Or, in the (abridged) words of the Standard:
There can be more than one definition of a class type ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then each definition of D shall consist of the same sequence of tokens.