Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > How to avoid multiple definition of a variable by multiple inclusion of a header file

Reply
Thread Tools

How to avoid multiple definition of a variable by multiple inclusion of a header file

 
 
lars.uffmann@rwth-aachen.de
Guest
Posts: n/a
 
      08-01-2006
Easily described problem:

Using g++ version 3.3.5 under suse 9.3,

bla.h:
-----------
#ifndef myTEST
#define myTEST
ZFSInt test;
#endif
------------

leads to an error at link time...
application.o(.bss+0x0):/path_here/application.cpp:19: multiple
definition of `test'
app.o(.bss+0x0):/path_here/app.cpp:17: first defined here
....for EVERY call of #include "bla.h"


Apparently the #ifndef only works at compile time, but somehow causes
an error at linktime. Any solution? I want the variable "test"
available in all modules that #include "bla.h"

Regards,

Lars Uffmann

 
Reply With Quote
 
 
 
 
Howard
Guest
Posts: n/a
 
      08-01-2006

<> wrote in message
news: oups.com...
> Easily described problem:
>
> Using g++ version 3.3.5 under suse 9.3,
>
> bla.h:
> -----------
> #ifndef myTEST
> #define myTEST
> ZFSInt test;
> #endif
> ------------
>
> leads to an error at link time...
> application.o(.bss+0x0):/path_here/application.cpp:19: multiple
> definition of `test'
> app.o(.bss+0x0):/path_here/app.cpp:17: first defined here
> ...for EVERY call of #include "bla.h"
>
>
> Apparently the #ifndef only works at compile time, but somehow causes
> an error at linktime. Any solution? I want the variable "test"
> available in all modules that #include "bla.h"
>


First, copy the definition of test above into an implementation file you'll
always link with (one which includes the header file where the definition of
ZFSInt resides). Then, preface the above declaration in blah.h with the
keyword "extern" (followed by at least one space). That tells the compiler
to look elsewhere for the actual declaration of test, allows other units to
see the variable through this header, and prevents the linker from seeing
multiple definitions.

-Howard



 
Reply With Quote
 
 
 
 
lars.uffmann@rwth-aachen.de
Guest
Posts: n/a
 
      08-01-2006
Howard wrote:
> First, copy the definition of test above into an implementation file you'll
> always link with (one which includes the header file where the definition of
> ZFSInt resides). Then, preface the above declaration in blah.h with the
> keyword "extern" (followed by at least one space).


Issue solved - thank you! I put the actual declaration in the cpp-file
belonging
to the blah.h class definition header file.

Any link to a website explaining this behaviour of #ifdef / #ifndef ?

Best Regards,

Lars

 
Reply With Quote
 
red floyd
Guest
Posts: n/a
 
      08-01-2006
wrote:
> Howard wrote:
>> First, copy the definition of test above into an implementation file you'll
>> always link with (one which includes the header file where the definition of
>> ZFSInt resides). Then, preface the above declaration in blah.h with the
>> keyword "extern" (followed by at least one space).

>
> Issue solved - thank you! I put the actual declaration in the cpp-file
> belonging
> to the blah.h class definition header file.
>
> Any link to a website explaining this behaviour of #ifdef / #ifndef ?


That's not a preprocessor issue, it's the ODR (one definition rule).
 
Reply With Quote
 
lars.uffmann@rwth-aachen.de
Guest
Posts: n/a
 
      08-02-2006
red floyd wrote:
> > Any link to a website explaining this behaviour of #ifdef / #ifndef ?

> That's not a preprocessor issue, it's the ODR (one definition rule).


To me, that doesn't explain why
#ifndef FOO
#define FOO
class foo {
foo(){};
~foo(){};
};

int test;
#endif

successfully avoids multiple class definition but NOT multiple
declaration of the variable "test" as an integer...

I used to think #ifdef and the likes were preprocessor commands that
would completely SKIP sections of code if the condition was not met -
all the way to the next #endif.
Apparently this does not work for variable declarations - That's the
part I do not understand.

Regards,

Lars

 
Reply With Quote
 
red floyd
Guest
Posts: n/a
 
      08-02-2006
wrote:
> red floyd wrote:
>>> Any link to a website explaining this behaviour of #ifdef / #ifndef ?

>> That's not a preprocessor issue, it's the ODR (one definition rule).

>
> To me, that doesn't explain why
> #ifndef FOO
> #define FOO
> class foo {
> foo(){};
> ~foo(){};
> };
>
> int test;
> #endif
>
> successfully avoids multiple class definition but NOT multiple
> declaration of the variable "test" as an integer...
>
> I used to think #ifdef and the likes were preprocessor commands that
> would completely SKIP sections of code if the condition was not met -
> all the way to the next #endif.
> Apparently this does not work for variable declarations - That's the
> part I do not understand.
>

Because you're defining a class... which is a type. No storage is
allocated. When you're declaring a variable, storage is allocated.

The other thing you need to know is that preprocessor commands don't go
across translation units.

 
Reply With Quote
 
Marco Costa
Guest
Posts: n/a
 
      08-02-2006
wrote:
> red floyd wrote:
>
>>>Any link to a website explaining this behaviour of #ifdef / #ifndef ?

>>
>>That's not a preprocessor issue, it's the ODR (one definition rule).

>
>
> To me, that doesn't explain why
> #ifndef FOO
> #define FOO
> class foo {
> foo(){};
> ~foo(){};
> };
>
> int test;
> #endif
>


Let's say that you include this file in two source files. What happens?
a) The class foo gets its declaration. Good, now you can create foo objects.
b) The integer test gets allocated. Once in one file and once in the second file.
Everything is fine until the link stage. The linker will try to make sense of all and will see *two* instances of int test. Which one to use? Nobody will ever be able to answer that.

The solution,

extern int test;

Goes in the header. That will tell to the compiler: There is a variable called test that is to be used, but it is only declared here. Its definition will be done somewhere else.

Then, in one of your source files, you define this variable on the normal way.
When you compile, you can refer to this variable in any source code that uses the include file, but at link time, only one instance will exist. At this point, no link error. Hooray!

I hope I was clear.

Regards,

Marco
 
Reply With Quote
 
=?ISO-8859-15?Q?Juli=E1n?= Albo
Guest
Posts: n/a
 
      08-02-2006
wrote:

> Any link to a website explaining this behaviour of #ifdef / #ifndef ?


You can imagine the preprocessor is a bunch of text editor macros. Do the
substitutions by hand, or use the commands or options of your compiler that
shows the preprocessor output, and look the generated code. This result is
what the "real" compiler see.

--
Salu2
 
Reply With Quote
 
Michiel.Salters@tomtom.com
Guest
Posts: n/a
 
      08-02-2006
wrote:
> Easily described problem:
>
> Using g++ version 3.3.5 under suse 9.3,
>
> bla.h:
> -----------
> #ifndef myTEST
> #define myTEST
> ZFSInt test;
> #endif
> ------------
>
> leads to an error at link time...
> application.o(.bss+0x0):/path_here/application.cpp:19: multiple
> definition of `test'
> app.o(.bss+0x0):/path_here/app.cpp:17: first defined here
> ...for EVERY call of #include "bla.h"
>
>
> Apparently the #ifndef only works at compile time, but somehow causes
> an error at linktime. Any solution? I want the variable "test"
> available in all modules that #include "bla.h"


Yes. You want the variable available. That means you'll need a
declaration,
not the definition. The typical variable declaration is "extern <type>
<name>;"
You put the definition in a .cpp, just like you would with function
definitions.

This has nothing to do with #ifdef, which is a preprocessor command. It
works only at compile time, and skips every second defintion of 'test'
*in
a single .cpp*, not across .cpp's. As the compiler works on single
..cpp's
it won't notice that.

HTH,
Michiel Salters

 
Reply With Quote
 
lars.uffmann@rwth-aachen.de
Guest
Posts: n/a
 
      08-02-2006
schrieb:
> This has nothing to do with #ifdef, which is a preprocessor command.
> It works only at compile time, and skips every second defintion of 'test'
> *in a single .cpp*, not across .cpp's. As the compiler works on single
> .cpp's it won't notice that.


Woohoo - I see light in the dark! Finally the explanation I've been
waiting for To be honest, I suspected something like this, because
the compiler creates libraries for each cpp file separately, so the
linker would spot multiple declarations of the variable, but in that
case the sense of the preprocessor commands did not occur to me - I
never realized it was only to skip further definitions within the same
cpp-File.

Thanks for clearing this up!
And to all the others that helped solving the problem!

Regards,

Lars

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
how to avoid multiple inclusion of a file suresh Ruby 5 06-11-2008 04:46 PM
tool to check multiple inclusion of header file techBoy C Programming 6 03-15-2006 10:49 AM
tool to check multiple inclusion of header file techBoy C++ 6 03-14-2006 12:29 PM
how to avoid using another header file inside a header file? Newsgroup - Ann C++ 4 11-02-2003 01:20 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57