C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: Who can explain this global variable behaviour?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Francis Glassborow
Guest





PostPosted: Thu Jun 26, 2003 2:23 pm    Post subject: Re: Who can explain this global variable behaviour? Reply with quote



In message <9d9b1b25.0306230900.5c017e6f (AT) posting (DOT) google.com>, me
<dkls (AT) hotmail (DOT) com> writes
Quote:
Hi,
Can some please explain to me the following:
I had an h file with some inline funcs.
All these funcs needed to update an array, so it was very conviniant
to make it
global.
I declared the global on top of the h file so: int g_lut[100];
The linker complained that Its multiple difiend - why? (it was the
only definition - i am sure!)

I solved this by trasforming the variable to -> static int g_lut[100].
Now the linker was happy and the code compiled through.
However, in run time, allthough all the inline functions updated the
array - whenever I looked into it, it was empty (as if it was not
changed)

Since I suspected it has to do with the defenition, I added a cpp
file, and decalred the global there, and added a global extern in the
h file.
Now the code works perfectly, and the updates in the array are
holding.

So waht is the reason/logic behind the linker complaining at the
begging, and why
do I have to declare in the cpp file the global for it to work?

Header files by their nature are lexically included into multiple
implementation files. Any global definitions (and a variable is defined
by default) are then present in each of those implementation files. The
linker sees all the object files and finds multiple definitions (one per

implementation file that included the header file in question).

Making the definition static produces multiple distinct versions of the
variable, one per file, that have no relationship with each other.

The qualification of a global variable as extern downgrades the
statement to a pure declaration, the necessary unique definition is
provided in a single implementation file.

There are three major exceptions to the requirement that header files
only contain declarations:

1) Type definitions (which are composed of declarations)
2) inline functions
3) template definitions

The compiler/linker is required to handle those.
In a different world we could have required that it handle other forms
of multiple definition but we did not because programmers can learn to
get it right.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Spangenberg
Guest





PostPosted: Thu Jun 26, 2003 2:25 pm    Post subject: Re: Who can explain this global variable behaviour? Reply with quote



Hello "me" (You?)

me schrieb:
[snip]

Quote:
I had an h file with some inline funcs.
All these funcs needed to update an array, so it was very conviniant
to make it
global.

In generally this is not the best reason to do this, but in the
following
I
will not criticize this decision any longer.
For the future you should collect informations concerning namespaces,
classes, and design patterns.

Quote:
I declared the global on top of the h file so: int g_lut[100];
The linker complained that Its multiple difiend - why? (it was the
only definition - i am sure!)


That is what we should expect, if the header file is #include'd by
several

translation units. Maybe your compiler creates precompiled header?
Declaring such a variable in a file implicitely declares (and defines !)
it to
be of external linkage. External linkage means, that this variable can
be
referred
to by its name from other translation units. This is ok, if its
definition
is
inside a single translation unit, but by defining it inside a header
file
this will
lead to multiple definitions of the same name inside each translation
unit
which
#include's this header file. This is a violation of the so named one
definition rule
or ODR (3.2/p. 3).
The effect is, that your linker sees multiple occurences of the same
object
name and doesn't know what to do ;-)

Quote:
I solved this by trasforming the variable to -> static int g_lut[100].
Now the linker was happy and the code compiled through.
However, in run time, allthough all the inline functions updated the
array - whenever I looked into it, it was empty (as if it was not
changed)

By declaring the global object with the of static attribute causes its
linkage
to be internal. Internal linkage means, that its name can only be
referred
to
by other scopes of the *single* translation unit, where it is defined.
By moving the definition into a header file, this will lead to multiple
instances
of g_lut arrays in the program: One instance per translation unit which
#include's this very header! This is not a violation of the ODR, but
also
not
what you want: Referring to one single named variable (a kind of
singleton).
The reason for the observation of the "empty" array is a nasty effect of
the combination of inline functions with multiple occurences of global
variables
with internal linkage and I am not sure whether this is a small hole of
the
inline specifications or a compiler bug. 7.1.2/p.4 demands, that
"An inline function shall be defined in every translation unit in which
it
is used
and shall have exactly the same definition in every case [..]".
Additionally it
says, that "A static local variable in an extern inline function always
refers to
the same object. A string literal in an extern inline function is the
same
object
in different translation units." Now none these two cases do apply,
because
you have a non-local static variable, so I am not sure whether the
inline
expansion was conforming or not. It obviously does not what you think it
should do. BTW: What do you mean by "whenever I looked into it"? It
could
mean that you looked at the different g_lut objects of the different
translation
units.

Quote:
Since I suspected it has to do with the defenition, I added a cpp
file, and decalred the global there, and added a global extern in the
h file.
Now the code works perfectly, and the updates in the array are
holding.


That is the correct way to solve this special problem. This has the
effect,
that the header just **declares** the existence of a named, arraylike
object
g_lut, but you are now satisfying the ODR also, because you make sure
that

only one definition of g_lut exists in your program by **defining** it
only
inside one single translation unit.

Hope that helps,

Daniel Spangenberg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.