Duplicate symbol error associated with const char * [] declaration - c++

I'd love help diagnosing the source of a duplicate symbol error that I'm receiving when I try to compile with g++ 4.2.1.
The specific error is
ld: duplicate symbol _SOCIODEM_FILENAMES in /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//ccP3yVgF.o and /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//cc1NqtRL.o
collect2: ld returned 1 exit status
The error occurs only when I include this declaration in a file called Parameters.h:
// Parameters.h
#ifndef PARAMETERS_H
#define PARAMETERS_H
// ...[code snipped]...
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
// ...[code snipped]...
#endif
I've searched all my files, and this is the only place where SOCIODEM_FILENAMES is declared. When I comment out the declaration, the 'duplicate symbol' error goes away.
I'm unfamiliar with linker errors (if that's what this is) and would appreciate help troubleshooting the problem. All my header files have #ifndef...#define...#endif wrappers. My compile command is
g++ -o a.out -I /Applications/boost_1_42_0/ Host.cpp Simulation.cpp main.cpp Rdraws.cpp
Thanks in advance.
Solution summary
I now have in Parameters.h:
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
All other definitions and declarations in Parameters.h are unchanged. Andrey and other commenters summarize an alternative approach using extern, which is overkill for my purposes.

For some reason none of the answers so far cared to explain the difference between your integer NUM_SOCIODEM_FILES object and array SOCIODEM_FILENAMES object. The latter triggers the linker error for the reasons already explained: because you include you header file into multiple implementation files. Yet, the former would link without any problems (because there are indeed no problems with NUM_SOCIODEM_FILES declaration). Why?
The reason for this is that your NUM_SOCIODEM_FILES object is declared const. In C++ const objects have internal linkage by default, meaning that they do not cause linking problems even if they are defined in multiple implementation files. In other words, in C++ your NUM_SOCIODEM_FILES is equivalent to
static const int NUM_SOCIODEM_FILES = 5; /* internal linkage */
which is why it does not lead to any linking problems.
At the same time your SOCIODEM_FILENAMES is not declared constant, which is why it gets external linkage by default and eventually leads to linker errors. But if you declare your SOCIODEM_FILENAMES as const as well, the problem will go away
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = {
...
Note where the extra const is placed in the declaration. If you just add that extra const and leave everything else as is (i.e. keep the definition if SOCIODEM_FILENAMES in the header file), the linker will not report the error even if you include your header file into multiple translation units.
This is not a recommended approach though, since that way you will give your SOCIODEM_FILENAMES internal linkage and end up with a standalone copy of SOCIODEM_FILENAMES array in each translation unit - something that might work fine but still makes very little sense. So, for your array, it is normally better to use the extern approach recommended in other answers.
However, note that you shouldn't normally do it for NUM_SOCIODEM_FILES declaration!!! It is fine as it is, defined in the header file. Unless you are trying to do something unusual, scalar constants should normally be defined with initializer in the header files - that way they can be seen as compile-time constants in all translation units, which is a rather valuable thing to have. So, beware of the strange advice present in some other answers to move the definition of NUM_SOCIODEM_FILES into .cpp file as well - this actually makes no sense and is a totally wrong thing to do.

Most likely, you are #includeing this file in multiple source files. The problem is that each inclusion results in a separate definition for a variable named SOCIODEM_FILENAMES. Include guards do not help with this. Include guards prevent multiple declarations within a single compilation unit; they do not prevent multiple definitions across several compilation units.
What you need to do is declare these variables as extern in the header, and then define them in exactly one source file. e.g.
// Parameters.h
#ifndef PARAMETERS_H
#define PARAMETERS_H
// ...[code snipped]...
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
// ...[code snipped]...
#endif
and then:
// Parameters.cpp (or some other source file)
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
You can get away with not doing this for the int because it is a constant integer, and so the compiler can just treat it as a compile-time constant, and it will never even show up in the compiled code. However, the char* cannot be treated this way, and so must have exactly one definition (known as the "one definition rule" in C++).

The header guard (#ifndef..#endif wrapper) just prevents you from including the same header multiple times in a single source file. You can still have multiple source files that include that header, and each one will declare that symbol separately. Since they all have the same name, linking those sources together will cause a symbol name collision. You probably want to declare the symbol in a source file instead of a header file

The problem is you are putting a definition in a header file. If you include that file in more than one compilation unit (.cpp file) you will be in effect creating multiple definitions and at link time you will get that error.
You need to put both those definitions in a .cpp file and put only a declaration in the header file:
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];

As others have suggested, one way of doing this is to declare NUM_SOCIODEM_FILES and SOCIODEM_FILENAMES as extern and define them once in an external file. The other way is to declare them as static--this causes them to be duplicated in every object file that includes the header, but will not create an error since the definition is private to that object file. Which option you choose is entirely up to your own preferences.

Related

Understanding C linker error: multiple definition

I have a project with multiple header files and .cpp files.
All of the header files have include guards.
There is a file called Constants.h where I define some constants. Some of these with defines, some as constant variables.
There are more header-.cpp-file pairs with code in them. One of these does contain a class, the others don't.
When I include my files into my main file (an arduino sketch), I get a lot of linker errors, claiming there are multiple definitions of some variables.
I read that this mainly occurs when you include .c or .cpp files, which I don't do. All the .cpp files only include their appropriate header files.
I did manage to find multiple solution proposals:
1) inline:
With functions, inline can be used to get rid of this problem. However, this is not possible with variables.
2) anonymous namespace:
This is one of the solutions I used. I put anonymous namespaces around all the problematic definitions I had. It did work, however I do not understand why this works. Could anyone help me understand it?
3) moving definitions into .cpp files:
This is another approach I used sometimes, but it wasn't always possible since I needed some of my definitions in other code, not belonging to this header file or its code (which I do admit is bad design).
Could anyone explain to me where exactly the problem lies and why these approaches work?
Some of these with defines, some as constant variables.
In C const does not imply the same thing as it does in C++. If you have this:
const int foo = 3;
In a header, then any C++ translation unit that includes the header will have a static variable named foo (the const at namespace scope implies internal linkage). Moreover, foo can even be considered a constant expression by many C++ constructs.
Such is not the case in C. There foo is an object at file scope with external linkage. So you will have multiple definitions from C translation units.
A quick fix would be to alter the definitions into something like this:
static const int foo = 3;
This is redundant in C++ but required in C.
In addition to Story Teller's excellent explanation, to define global variables, use the following:
// module.h
#include "glo.h"
// glo.h
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myvar;
// main.c
#define EXTERN
#include "glo.h"
In main.c all variables will be declared (i.e. space is allocated for them), in all other c files that include glo.h, all variables will be known.
You shouldn't declare any object in header files, this should be moved to c\c++ files.
In header you may:
declare types such as: classes, structs, typedefs etc.
put forward declarations of (not classes) functions
put inline (or in classes) functions (+ body)
you may add extern declaration.
you may put your macros.
a static declaration may declare things multiple times, therefore it is not recommended.

duplicate symbol error C++

I have added some const character in my file as under. The error i get is duplicate symbol _xyz(say). What is the problem with it and how could i get out of this.
const char* xyz = "xyz";
class Abc
{
public:
Abc()
{
}
};
If this is in a header file, you're defining xyz every time you #include it.
You can change the declaration as #R Samuel Klatchko shows. The usual way (if the data isn't const) is like this:
In Abc.h:
extern char *xyz;
In Abc.cpp:
char *xyz = "xyz";
Edited to add
Note that header guards will not solve this problem:
#ifndef XYZ_H
#define XYZ_H
...
#endif
Header guards prevent "redefinition" errors, where the same symbol appears twice in the same compilation unit. That's a compiler error.
But even with header guards the definition of xyz will still appear in every source file that includes it, causing a "duplicate symbol" error, which is a linker error.
It would have been more helpful if the original poster had mentioned that, of course.
The problem is every source file that includes your header file gets it's own copy of xyz with external linkage.
The easiest way to fix that is to give xyz internal linkage. You can do that by making the pointer itself const in addition to having the underlying char's const:
const char* const xyz = "xyz";
I also ran into this issue, but for me the solution was different. I had put overloaded operators (==, !=, <<) in my header file and implemented them. This was causing an issue in other files where I also used ==, !=, or <<. To solve this, I moved the implementation into the .cpp file and left the declaration in the header file.
Edit:
This can also be caused if:
You are including .cpp files instead of .h files. You can fix this by switching the import to use .h instead of .cpp.
You are implementing static functions inside a header file (outside of the class declaration). You can fix this by moving the implementations into a .cpp file (among other solutions).
My use-case:
I had multiple header files a.hpp, b.hpp, and, c.hpp which contained some utility methods.
I had a file util.hpp which acted as an aggregator for the above files.
In my case, the extern did not work but static worked.
I had to use:
header guards to avoid errors in Visual Studio code.
static with functions to avoid compile-time errors.
Check out this article too.

How does one avoid accidentally redeclaring global constants in C++?

I have a template matrix class class defined in a header called "Matrix.h".
Certain matrices are used repeatedly in my program. I thought that I would define these in the "Matrix.h" header file, like so:
const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
When I do this g++ complains that I redefined the constant in question. This happens because I include Matrix.h in two different source files. When the object files for these are compiled, both end up with a definition of the matrix above, causing the error message.
My question is how do I avoid this situation? I want a constant that is accessible to more than one file, but I don't know where to put it.
You avoid it by:
Declaring it extern in the header. A symbol can be declared any number of times.
Defining it in the implementation, only once.
If you don't want to split it between a header and implementation file,
Declare your constant static (or declare it in anonymous namespace) to make definition private. Linker will not complain, but it will result in multiple private copies across compilation units.
static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
Make an inline function that returns the constant. Inline function definitions produce "weak" symbols in object file, so linker will eliminate duplicates and pick one.
inline const Matrix<GLfloat>&
GET_B_SPLINE_TO_BEZIER_MATRIX() {
const static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
return B_SPLINE_TO_BEZIER_MATRIX;
}
just write your header file like this
#ifndef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H
// your header file code
#endif
this will make sure that it won't get declared multiple times
Wrap header files (.h) in preprocessor conditionals to prevent them from being included in the compiler's symbol table twice:
#ifndef HEADER_NAME
#define HEADER_NAME
// code...
#endif//HEADER_NAME
HEADER_NAME can really be anything, but it's best to make sure that it's something related to the file to prevent more collisions, as this is just defining an empty preprocessor macro (which also ends up in the symbol table).

Header Guards and LNK4006

I have a character array defined in a header
//header.h
const char* temp[] = {"JeffSter"};
The header if #defined guarded and has a #pragma once at the top. If this header is included in multiple places, I get an LNK4006 - char const * * temp already defined in blahblah.obj. So, I have a couple of questions about this
Why does this happen if I have the guards in place? I thought that they prevented the header from being read in after the first access.
Why do the numerous enums in this header not also give the LNK4006 warnings?
If I add static before the signature, I don't get the warning. What are the implications of doing it this way.
Is there a better way to do this that avoids the error, but lets me declare the array in the header. I would really hate to have a cpp file just for an array definition.
Why does this happen if I have the guards in place? I thought that they prevented the header from being read in after the first access.
Include guards make sure that a header is included only once in one file (translation unit). For multiple files including the header, you want the header to be included in each file.
By defining, as opposed to declaring variables with external linkage (global variables) in your header file, you can only include the header in once source file. If you include the header in multiple source files, there will be multiple definitions of a variable, which is not allowed in C++.
So, as you have found out, it is a bad idea to define variables in a header file for precisely the reason above.
Why do the numerous enums in this header not also give the LNK4006 warnings?
Because, they don't define "global variables", they're only declarations about types, etc. They don't reserve any storage.
If I add static before the signature, I don't get the warning. What are the implications of doing it this way.
When you make a variable static, it has static scope. The object is not visible outside of the translation unit (file) in which it is defined. So, in simple terms, if you have:
static int i;
in your header, each source file in which you include the header will get a separate int variable i, which is invisible outside of the source file. This is known as internal linkage.
Is there a better way to do this that avoids the error, but lets me declare the array in the header. I would really hate to have a cpp file just for an array definition.
If you want the array to be one object visible from all your C++ files, you should do:
extern int array[SIZE];
in your header file, and then include the header file in all the C++ source files that need the variable array. In one of the source (.cpp) files, you need to define array:
int array[SIZE];
You should include the header in the above source file as well, to allow for catching mistakes due to a difference in the header and the source file.
Basically, extern tells the compiler that "array is defined somewhere, and has the type int, and size SIZE". Then, you actually define array only once. At link stage, everything resolves nicely.
Include guards protect you from including the same header into the same file repeatedly - but not from including it in distinct files.
What happens is that the linker sees temp in more then one object file - you can solve that by making temp static or putting it into an unnamed namespace:
static const char* temp1[] = {"JeffSter"};
// or
namespace {
const char* temp2[] = {"JeffSter"};
}
Alternatively you can use one source file which defines temp and just declare it as extern in the header:
// temp.cpp:
const char* temp[] = {"JeffSter"};
// header.h:
extern const char* temp[];
Header guards have absolutely nothing to do with preventing multiple definitions in your entire program. The purpose of header guards is to prevent multiple inclusion of the same header file into the same translation unit (.cpp file). In other words, they exist to prevent multiple definitions in the same source file. And they do work as intended in your case.
The rule that governs multiple-definition issues in C++ is called One Definition Rule (ODR). ODR is defined differently for different kinds of entities. For example, types are allowed to have multiple identical definitions in the program. They can (and most always have to) be defined in every translation unit where they are used. This is why your enum definition does not result in an error.
Objects with external linkage are a completely different story. They have to be defined in one and only one translation unit. This is why your definition of temp causes an error when you include the header file into multiple translation units. Include guards can't prevent this error. Just don't define objects with external linkage in header files.
By adding static you give your object internal linkage. This will make the error disappear, since now it is perfectly OK from ODR point of view. But this will define an independent temp object in each translation unit into which your header file is included. To achieve the same effect you could also do
const char* const temp[] = { "JeffSter" };
since const objects in C++ have internal linkage by default.
This depends on whether you need an object with external linkage (i.e. one for the entire program) or an object with internal linkage (unique to each translation unit). If you need the latter, use static and/or extra const (if that works for you) as shown above.
If you need the former (external linkage), you should put a non-defining declaration into the header file
extern const char* temp[];
and move the definition into one and only one .cpp file
char* const temp[] = { "JeffSter" };
The above declaration in the header file will work for most purposes. However, it declares temp as an array of unknown size - an incomplete type. If you wish to declare it as an array of known size, you have to specify the size manually
extern const char* temp[1];
and remember to keep it in-synch between the declaration and definition.
I respectfully disagree with the advice against defining variables in headers, because I think "never" is too broad. Nevertheless, the episode that brought me to this thread offers a cautionary tale for those who dare to do so.
I landed on this page as the result of an inquiry into the cause of warning LNK4006, calling out a long established array that I just moved from the translation unit that defines my DLLMain routine into the private header that is included in most of the translation units that comprise this library. I have compiled this library hundreds of times over the last 11 years, and I had never before seen this warning.
Shortly after I read this page, I discovered the cause of the error, which was that the definition was outside the guard block that protects everything else that is defined in the module that also defines DLLMain, which is where I usually gather all the memory blocks that need external linkage. As expected, moving the table inside the guard block eliminated the warnings, leaving me with only two, related to a brand new externally linked table, to be resolved.
Takeaway: You can define variables in headers, and it's a great place to put common blocks, but mind your guards.
Hang on... you are mixing up your declarations...you did say 'char const * * temp' yet in your header file you have 'const char* temp[] = {"JeffSter"};'.
See section 6.1 of the C FAQ, under 'Section 6. Arrays and Pointers', to quote:
6.1: I had the definition char a[6] in one source file, and in
another I declared extern char *a. Why didn't it work?
A: In one source file you defined an array of characters and in the
other you declared a pointer to characters. The declaration
extern char *a simply does not match the actual definition.
The type pointer-to-type-T is not the same as array-of-type-T.
Use extern char a[].
References: ISO Sec. 6.5.4.2; CT&P Sec. 3.3 pp. 33-4, Sec. 4.5
pp. 64-5.
That is the source of the problem. Match up your declaration and definitions. Sorry if this sounds blunt, but I could not help noticing what the linker was telling you...

Anyone knows how to fix compile error: LNK2005? (Source Code inside)

I have the below code in stdafx.h.
using namespace std;
typedef struct {
DWORD address;
DWORD size;
char file[64];
DWORD line;
} ALLOC_INFO;
typedef list<ALLOC_INFO*> AllocList;
//AllocList *allocList;
Without the commented code (last line), it compiles just fine. But when I add the commented code, Im getting the following error.
error LNK2005: "class std::list >
* allocList" (?allocList##3PAV?$list#PAUALLOC_INFO##V?$allocator#PAUALLOC_INFO###std###std##A)
already defined in test.obj
Im using Visual Studio .NET 2003. Anyone has any idea what that is and how to solve it?
Don't put definitions in header files, just declarations. Declarations specify that something exists while definitions actually define them (by allocating space). For example typedef, extern and function prototypes are all declarations, while things like struct, int and function bodies are definitions.
What's happening is that you're most likely including stdafx.h in multiple compilation units (C++ source files) and each of the resulting object files is getting its own copy of allocList.
Then when you link the objects together, there's two (or more) things called allocList, hence the link error.
You would be better off declaring the variable:
extern AllocList *allocList;
in your header file and defining it somewhere in a C++ source file (such as a main.cpp):
AllocList *allocList;
That way, every compilation unit that includes stdafx.h will know about the external variable, but it's only defined in one compilation unit.
Based on your further information:
I was trying to follow http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml, I assume that all those code are meant to be placed in the stdafx.h. Any other alternatives, pax?
My response is as follows.
I wouldn't put them in stdafx.h myself since I think that uses some MS magic for pre-compiled headers.
Make a separate header file mymemory.h and put your function prototypes in it, for example (note that this has no body):
inline void * __cdecl operator new(
unsigned int size,
const char *file,
int line);
Also in that header, put the other prototypes for AddTrack(), DumpUnfreed(), etc., and the #define, typedef and extern statements:
extern AllocList *allocList;
Then, in a new file mymemory.cpp (which also contains #include "mymemory.h"), put the actual definition of allocList along with all the real functions (not just the prototypes) and add that file to your project.
Then, #include "mymemory.h" in every source file in which you need to track memory (probably all of them). Because there are no definitions in the header file, you won't get duplicates during the link and because the declarations are there, you won't get undefined references either.
Keep in mind that this won't track memory leaks in code that you don't compile (e.g., third-party libraries) but it should let you know about your own problems.
I was trying to follow this article, I assume that all those code are meant to be placed in the stdafx.h. Any other alternatives pax?