Duplicate symbol issue with C headers - c++

This is my first time tackling a CUDA project that's slightly more complex than the simple write-single-source-file-and-compile routine. As expected, I'm facing some issues with C headers, namely duplicated symbols.
According to the linker, conflicts arise over the inclusion of the following header file in multiple .cu files:
env_vars.h
#ifndef ENV_VARS_H_
#define ENV_VARS_H_
/*** GLOBAL VARIABLES ***/
unsigned int h_n_osc;
__device__ unsigned int d_n_osc;
/*** CONSTANTS ***/
const double OMEGA_0 = 6.447421494058077e+09;
/* other constants defined in the middle */
#endif
multigpu.cu
#include "env_vars.h"
/* assigns h_n_osc */
adm_matrix.cu
#include "env_vars.h"
/* uses h_n_osc */
Building the project in Nsight Eclipse Edition results in the linker complaining about the h_n_osc variable being defined twice:
duplicate symbol _h_n_osc in:
./adm_matrix.o
./multigpu.o
ld: 1 duplicate symbol for architecture x86_64
Searching through the Internet, I've realized that moving the declaration of the h_n_osc variable to multigpu.cu and re-declaring it as an extern variable in adm_matrix.cu (and wherever I might need it later) solves the problem, which in fact it does.
Problem solved, but I'd like to take a deeper look into this:
Why doesn't the linker complain about the d_n_osc variable as well? And why are the constants (such as OMEGA_0) equally not a problem?
Does this mean that it is not possible to place global variables in header files?
What puzzles me most is that a number of sources over the Internet state that duplicated symbol errors should happen only when the header file contains a definition of the variable, while its simple declaration shouldn't constitute a problem. The reason I have a hard time believing this is that I'm facing the issue even though my header only contains a declaration! Am I missing something?
Thanks in advance for your patience, folks!

Header files should normally contain only declarative code. h_n_osc should be declared here, not defined.
extern unsigned int h_n_osc;
In at least one of your modules, or a new one of its own you will need a definition; for example:
env_vars.cu
#include "env_vars.h"
unsigned int h_n_osc;
Then link that. Alternatively you could of course place the definition in one of the existing modules multigpu.cu or adm_matrix.cu.
I am not sure of the semantics of the The CUDA __device__ extension, while it may link, it is not necessarily correct; you may end up with each module referencing a separate copy of the device variable; it may be necessary to qualify that with extern as well. This question appears to deal with that issue.

Related

I'm having an 2D Array Redefinition Error

There is an error (actually 3 same errors) with my definition array int mang[max][max] and I couldn't find anything to fix it properly, so I hope someone will notice my question and help me soon. XD
In my header file array.h, I have:
#include <iostream>
#define max 100
using namespace std;
int mang[max][max];
void NhapMang(int mang[][max], int hang, int cot);
void XuatMang(int mang[][max], int hang, int cot);
int TinhTongPhanTu(int mang[][max], int hang, int cot);
int DemPhanTux(int mang[][max], int hang, int cot);
When I was typing my code, VS shows me that there is "no issues found" all over .cpp files, but when I debug the code, the error appears in the header file array.h, says "C2086 'int mang[100][100]': redefinition" altogether.
I think that I've defined mang twice or more, but I couldn't find the other mang definition nor fixing it if I found. This is the capture of the error list.
I don't know what parts I need provide to you in my project to help fixing it for me (and I also think my post would become so long to read if I copy-paste all my code up here :-( ), so if you need any further information, just comment and I will give it to you.
And well, I've just start learning C++ for 3 months, so there's soooo many things I haven't known yet XD If there's anything I couldn't understand in the way you fix the problem, please let me ask you more about it.
Hope you understand what I mean XD (cuz I'm not a native speaker). And thank you for reading.
The language rules say:
[basic.def.odr]
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required. ...
(There are some exceptions with limitations that are listed in further rules, but none that apply to your example)
int mang[max][max];
This is definition of a variable. That definition is in a header file. Header files are typically included into multiple translation units. If you do so, then you have included the definition of the variable into multiple translation units. By having multiple definitions of a non-inline variable, you would violate the rule quoted above.
The key here is that the pre-processor is a text altering engine. In every file where you have #include "array.h", the textual contents of array.h are inserted in place of the #include.
So, if you have several files that include array.h then each one of those files declares and defines mang (all using the same definition). That isn't a problem during compilation because each file is compiled separately, but they each generate an object file that defines mang.
Then you try to link, and the linker sees several defitions of the array.
The solution is the same as the one you are using for functions in array.h: you declare in the header and define in the implementation (presumably array.cpp).
How do you declare an array without defining it?
Good question. I'm glad you asked. You do it with the extern keyword like this.
array.h:
// ...
#define max 100
extern int mang[max][max]; // <=== Look here (with extern)
// ...
Then you define it in array.cpp:
// ...
int mang[max][max]; // <== and compare to this (no extern)
// ..
As an aside you using the pre-processor to define constants (like #define max 100 has several downsides, and in c++ you are generally better off using compile-time constants like
const int max = 100; // Pre c++11
or
constexpr int max = 100; // c++11 or later
(The use of the pre-processor for this is a holdover from ancient days when compilers were a lot less clever.)

Why doesn't #pragma once guard against multiple non-constexpr definitions?

Just spent a while debugging a multiple definition error but I'm unclear on why this behavior occurred and would like to understand.
I had something similar to this in a header file.
//foo.h
#pragma once
my_states States[N] = {...};
Later, bar.h includes foo.h as bar.cpp has functions which need to know about my_states.
The issue arose when I was writing unit tests for bar and included bar.h in test.cpp.
bar.o: multiple definition of MyNamespace::named_states
test.o: first defined here
I have fixed the issue by changing to
constexpr my_states States[n] = {...}; in foo.h.
However I do not understand why this fixed the issue. I understand I had multiple definitions for the symbol my_states which confused the linker, but if I have my #pragma once guard in place, why was this being defined multiple times? I'm unsure why I need the constexpr qualifier to denote that this should only have 1 definition, when as far as I understand #pragma once should have prevented the compiler from attempting to create more than 1 definition in the first place.
#pragma once only ensures that header files are included once only, it doesn't deal with the code.
On your second question regarding my_states - without constexpr you attempt to define a global variable that can be modified in runtime (or something like that). By settings its state in the header, you defacto make each library that includes this header file instantiate and contain the variable while it is supposed to be uniquely defined... basically it's a complete mess that cannot compile. You can declare static/global variables in header files but you ought to instantiate them in a single cpp file.
By adding constexpr to the variable declaration you convey to compiler that it cannot be modified in runtime, and moreover, it's value is known at compile time. So there is no worry about which library stores / instantiates it or anything of the sort since it is an absolute constant known at compile time.

Definition and declaration of global variables using preprocessor trick

I am currently looking through the code written by senior engineer. The code works fine but i am trying to figure out one detail.
He uses quite a few global variables and his code is broken down into a lot of separate files. So he uses a technique to make sure that global vars are declared everywhere where he needs to access them but are only defined once.
The technique is new to me but I read few articles on the internet and got some understanding about how it works. He uses
#undef EXTERN
followed by conditional definition of EXTERN as an empty string or actual extern. There is a very good article here explaining how it works. Also there is a discussion here
What gets me confused is that all examples I saw on the web suggest to include header file in a regular way in all of the source files that need it except for one. In this single special case line that includes header is preceded by definition of a symbol that will ensure that EXTERN will be defined to an empty string and .. so on (see link above). Typically this single special case is in main or in a separate source file dedicated to the declaration of global variables.
However in the code that I am looking at this special case is always in the source file that corresponds the header. Here is the minimal example:
"peripheral1.h" :
#undef EXTERN
#ifndef PERIPHERAL_1_CPP
#define EXTERN extern
#else
#define EXTERN
#endif
EXTERN void function1(void);
"peripheral1.cpp" :
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
function1()
{
//function code code here
}
Everywhere else in the code he just does
#include "peripheral1.h"
My question is how and why does that work? In other words, how does compiler know where to define and where to just declare function (or variable, or class ...)? And why is it ok in above example to have the lines :
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
in actual peripheral1.cpp rather then in main.cpp or elsewhere?
Or am I missing something obvious here?
All the source files, except "perripheral1.cpp", after preprocessing contain a sequence
of external variable declarations like:
extern int a;
extern int b;
extern int c;
In peripheral1.cpp only, after preprocessing, there will be a sequence of declarations:
int a;
int b;
int c;
int d;
which are tentative definitions of the corresponding variables, which, under normal circumstances are equivalent of the external definitions :
int a = 0;
int b = 0;
int c = 0;
int d = 0;
End result is, variable are declared everywhere, but defined only once.
PS. To be perfectly clear ...
In other words, how does compiler know where to define and where to
just declare function (or variable, or class ...)?
The compiler knows where to declare, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a declaration.
The compiler knows where to define, whenever it encounters a grammatical construct, which is defined in the standard to have the semantics of a definition.
In other other words, the compiler does not know - you tell it explicitly what you want it to do.
Nostalgia
Ahh, this takes me back a fair way (about 20 years or so).
This is a way for C code to define global variables across multiple files: you define the variable once using a macro to ensure it is defined exactly only once, and then extern it in other C code files so you can utilise it. Nowadays it is quite superfluous in many instances, however it still has its place in legacy code, and will (most likely) still work in many modern compilers, nut it is C code not C++.
Normally the likes of #define PERIPHERAL_1_CPP is utilised to ensure uniquenesss of inclusion like a #pragma once
In my own code I would use something like:
#ifndef PERIPHERAL_1_CPP
#define PERIPHERAL_1_CPP
// my includes here
// my code here
#endif
That way you can #include the file as many times as you want all over your code, in every code file even, and you will avoid multiple definition errors. To be fair I normally do it with the .h files and have something like:
// for absolutely insane safety/paranoia
#pragma once
// normally sufficient
#ifndef PERIPHERAL_1_H
#define PERIPHERAL_1_H
// my includes here
// my code here
#endif
I have never tried it on cpp files but wil llater tonight to see if there is any benefit one way or the other:)
Give me a shout if you need any more info:)

Duplicate symbol error associated with const char * [] declaration

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.

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?