multiple definition error - global variable header file

B

Bram Kuijper

Hi all,

I am having a classical 'multiple definition error' of a global
variable, but this time I cannot find a good explanation of how to
prevent this multiple definition error.

I defined a global variable, needed by some functions, inside a header
file with ifndef clauses in order to prevent multiple definition:

#ifndef _MYRANDOM_H_
#define _MYRANDOM_H_

long int idum;
long int idum2;

// some function declarations etc

#endif
// end of header file


The functions declared in this header file are put in a static library.
Subsequently, this static library is used by a number of other static
libraries. Compiling these static libraries does not yield any errors.

Next to that I compile a program using those static libraries and
subsequently the errors surface. Errors like:

/home/bram/Varsity/C++/Simulation_classes/Trait/express.cpp:48: multiple
definition of `idum'
/tmp/cciYexgh.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libtrait.a(express.o): In function
`__static_initialization_and_destruction_0':
/home/bram/Varsity/C++/Simulation_classes/Trait/express.cpp:48: multiple
definition of `idum2'
/tmp/cciYexgh.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libtrait.a(inherit.o): In function
`__static_initialization_and_destruction_0':
/home/bram/include/gene.h:55: multiple definition of `idum'

How can it be that when I use this header file, the variables are
redefined _despite_ me using #ifndef clauses? I am using g++ 4.1.3 on a
ubuntu linux box and I did not define any of those variables outside the
header file.

thanks in advance,

Bram
 
C

Colander

Hi all,

I am having a classical 'multiple definition error' of a global
variable, but this time I cannot find a good explanation of how to
prevent this multiple definition error.
#ifndef _MYRANDOM_H_
(as a side note, it's better to use __MYRANDOM_H__, stuff starting
with an _ and followed by a capital is reserved for implementation)
The functions declared in this header file are put in a static library.
Subsequently, this static library is used by a number of other static
libraries. Compiling these static libraries does not yield any errors.

Next to that I compile a program using those static libraries and
subsequently the errors surface. Errors like:

I think you variable is present in the library AND in the executable.
To test this you can first compile your lib, change the headers so the
global var is gone and the compile your program, the error should be
gone. Later on you can simulate the removing trick with some xtrat
define that is defined for the lib but not for the program.

Veel succes,
Bas
 
B

Bram Kuijper

I think you variable is present in the library AND in the executable.
To test this you can first compile your lib,

okay, compiled my libraries with the global variables still in there


change the headers so the
global var is gone

commented out the global variables.

and the compile your program, the error should be

subsequently, I compiled the program, now including the header in which
the global vars are commented out.

Unfortunately the errors are still there. I have no clue:


g++ -g -Wall -I/home/bram/include -L/home/bram/lib -o spatial main.cpp
-lsimulation -lparameters -lworld -lpatch -lindividual -ltrait -lgene
-lbramrandom
/home/bram/lib/libsimulation.a(run.o): In function
`__static_initialization_and_destruction_0':
/home/bram/Varsity/C++/Simulation_classes/Simulation/run.cpp:29:
multiple definition of `idum'
/tmp/ccTdhYH6.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libsimulation.a(run.o): In function
`__static_initialization_and_destruction_0':
/home/bram/Varsity/C++/Simulation_classes/Simulation/run.cpp:29:
multiple definition of `idum2'
/tmp/ccTdhYH6.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libsimulation.a(simulation.o): In function
`__static_initialization_and_destruction_0':
/home/bram/include/parameters.h:11: multiple definition of `idum'
/tmp/ccTdhYH6.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libsimulation.a(simulation.o): In function
`__static_initialization_and_destruction_0':
/usr/include/c++/4.1.3/bits/stl_vector.h:96: multiple definition of `idum2'
/tmp/ccTdhYH6.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libworld.a(disperse.o): In function
`__static_initialization_and_destruction_0':
/usr/include/c++/4.1.3/bits/stl_vector.h:95: multiple definition of `idum'
/tmp/ccTdhYH6.o:/home/bram/Varsity/genconfl/haplodiploidy/spatial/main.cpp:14:
first defined here
/home/bram/lib/libworld.a(disperse.o): In function
`__static_initialization_and_destruction_0':
/usr/include/c++/4.1.3/bits/stl_vector.h:96: multiple definition of `idum2'
 
M

Marcus Kwok

Colander said:
(as a side note, it's better to use __MYRANDOM_H__, stuff starting
with an _ and followed by a capital is reserved for implementation)

That's even worse. Identifiers with a double-underscore (I think it may
be anywhere in the name) are also reserved for the implementation.

However, trailing underscores are OK. I would use MYRANDOM_H_ or
something like that.
 
C

Colander

That's even worse. Identifiers with a double-underscore (I think it may
be anywhere in the name) are also reserved for the implementation.

Damn, thanks, I will remember that one!
 
J

joe

long int idum;
long int idum2;

Your header guards are insufficient to prevent double definition
errors because there is more than one compilation unit including the
header. Each .cpp which includes the header will define its own
globals. The header guard only prevents a single compilation unit
from including the header more than once. What you need to do is
something like one of the following...

suggestion 1: Change the declarations in your header to:

extern long int idum;
extern long int idum2;

Then actually define these guys in one of your .cpp files.

suggestion 2: Modify your header to something like:

#ifdef DEFINE_GLOBALS
#define GLOBAL
#else // !DEFINE_GLOBALS
#define GLOBAL extern
#endif

GLOBAL long int idum;
GLOBAL long int idum2;

One of your .cpp files should define "DEFINE_GLOBALS" prior to
including this header. The only real advantage of this method over
the 1st is that you are then guaranteed that your definition and
declarations match.

Suggestion 3: Encapsulate the globals into one .cpp and provide
accessors to access/set the globals. This one is a bit of fuss, so I
don't like it so much, but...

long get_idum();
set_idum(long);

long get_idum2();
set_idum(long);

then in a .cpp you define:

long int idum;
long int idum2;

long int get_idum()
{
return idum;
}

void set_idum(long int v)
{
idum = v;
}
..
..
..


You should also consider putting your globals in your own namespace so
that they can't conflict with any other globals in the system.

Hope that helps,
joe
 
R

red floyd

Colander said:
(as a side note, it's better to use __MYRANDOM_H__, stuff starting
with an _ and followed by a capital is reserved for implementation)

WRONG WRONG WRONG! You are correct in that _ followed by upper case is
reserved, but any identifier containing a double underscore is also so
reserved. He should use MYRANDOM_H_
 
J

James Kanze

(as a side note, it's better to use __MYRANDOM_H__, stuff starting
with an _ and followed by a capital is reserved for implementation)

As is anything containing two adjacent underscore. And anything
at all beginning with an underscore in the global namespace (and
thus, macros).
I think you variable is present in the library AND in the executable.

I think his problem is that the definition is present in every
translation unit that includes the header. Include guards only
prevent multiple definitions in a single translation unit; they
have no effect between translation units. What he needs to do
is replace the definitions in the header with declarations, and
provide a definition in a single source file, e.g.:

in header:
// ...
extern long int idum ;
extern long int idum2 ;
// ...

and in a single source file (which preferably includes the
header):

long int idum = ... ;
long int idum2 = ... ;

(Note that unlike a function declaration, a data declaration is
a definition unless it is explicitly declared extern.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top