initialization sequence issue



 DEVELOP > c-Plus-Plus > initialization sequence issue

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > c-Plus-Plus
User: "Christof Warlich"
Date: 05 Jan 2008 12:17:19 PM
Object: initialization sequence issue
Hi,
the few lines of code below show different results depending on
the compiler version (gcc-2.95 versus gcc-3.3 and later):
gcc-2.95 first initializes d (line 9) and then t (line 8), as
running the executable yields
initialized d
X constructor
whereas gcc-3.3 and later gcc versions do as I'd expect: They
initialize the variables as they appear in the source code:
X constructor
initialized d
Could anyone tell if the initialization sequence is specified
by the standard in such a case or if I cannot rely on the
initialization sequence even when everything is in the same translation
unit?
Thanks,
Christof
1 #include <stdio.h>
2 struct X {
3 X() {printf("X constructor\n");}
4 };
5 template<typename T> struct A {
6 static T t;
7 };
8 template<typename T> T A<T>::t;
9 X &x = A<X>::t;
10 int d = printf("initialized d\n");
11 int main() {}
.

User: "Salt_Peter"

Title: Re: initialization sequence issue 05 Jan 2008 01:31:24 PM
On Jan 5, 1:17 pm, Christof Warlich <cwarl...@gmx.de> wrote:

Hi,

the few lines of code below show different results depending on
the compiler version (gcc-2.95 versus gcc-3.3 and later):

gcc-2.95 first initializes d (line 9) and then t (line 8), as
running the executable yields

initialized d
X constructor

whereas gcc-3.3 and later gcc versions do as I'd expect: They
initialize the variables as they appear in the source code:

X constructor
initialized d

Could anyone tell if the initialization sequence is specified
by the standard in such a case or if I cannot rely on the
initialization sequence even when everything is in the same translation
unit?

Thanks,

Christof

1 #include <stdio.h>
2 struct X {
3 X() {printf("X constructor\n");}
4 };
5 template<typename T> struct A {
6 static T t;
7 };
8 template<typename T> T A<T>::t;
9 X &x = A<X>::t;
10 int d = printf("initialized d\n");
11 int main() {}

section 3.6.2
The storage for objects with static storage duration shall be zero
initialized before any other initilization takes place
section 3.7.1 says
The keyword static applied to a class data member in a class
definition gives the data member static storage duration.
(does not cover those static members in a namespace scope!)
.
User: "Rahul"

Title: Re: initialization sequence issue 06 Jan 2008 07:44:01 AM
On Jan 6, 12:31 am, Salt_Peter <pj_h...@yahoo.com> wrote:

On Jan 5, 1:17 pm, Christof Warlich <cwarl...@gmx.de> wrote:



Hi,


the few lines of code below show different results depending on
the compiler version (gcc-2.95 versus gcc-3.3 and later):


gcc-2.95 first initializes d (line 9) and then t (line 8), as
running the executable yields


initialized d
X constructor


whereas gcc-3.3 and later gcc versions do as I'd expect: They
initialize the variables as they appear in the source code:


X constructor
initialized d


Could anyone tell if the initialization sequence is specified
by the standard in such a case or if I cannot rely on the
initialization sequence even when everything is in the same translation
unit?


Thanks,


Christof


1 #include <stdio.h>
2 struct X {
3 X() {printf("X constructor\n");}
4 };
5 template<typename T> struct A {
6 static T t;
7 };
8 template<typename T> T A<T>::t;
9 X &x = A<X>::t;
10 int d = printf("initialized d\n");
11 int main() {}


section 3.6.2
The storage for objects with static storage duration shall be zero
initialized before any other initilization takes place

section 3.7.1 says
The keyword static applied to a class data member in a class
definition gives the data member static storage duration.
(does not cover those static members in a namespace scope!)

But aren't global variables static by default? static for a global
variable just reduces the visibility scope of the global variable to
that particular compilation unit, isn't it?
.
User: "Christof Warlich"

Title: Re: initialization sequence issue 06 Jan 2008 11:48:29 AM
Rahul schrieb:

section 3.7.1 says
The keyword static applied to a class data member in a class
definition gives the data member static storage duration.
(does not cover those static members in a namespace scope!)


But aren't global variables static by default? static for a global
variable just reduces the visibility scope of the global variable to
that particular compilation unit, isn't it?

Absolutely right, that's my understanding as well.
.


User: "Christof Warlich"

Title: Re: initialization sequence issue 05 Jan 2008 05:25:41 PM
Salt_Peter schrieb:

Could anyone tell if the initialization sequence is specified
by the standard in such a case or if I cannot rely on the
initialization sequence even when everything is in the same translation
unit?

section 3.6.2
The storage for objects with static storage duration shall be zero
initialized before any other initilization takes place

ok, but in my case, both variables are explicitly initialized to
non-zero values.


section 3.7.1 says
The keyword static applied to a class data member in a class
definition gives the data member static storage duration.
(does not cover those static members in a namespace scope!)

What I really like to know is if I usually could rely on having
my global variables being initialized in the same sequence as
they appear in the source code, i.e. whether the old gcc-2.95
compiler is buggy because it initializes d _before_ t or if this
is an implementation detail that is not defined by the standard.
.
User: "Salt_Peter"

Title: Re: initialization sequence issue 05 Jan 2008 07:44:41 PM
On Jan 5, 6:25 pm, Christof Warlich <cwarl...@gmx.de> wrote:

Salt_Peter schrieb:

Could anyone tell if the initialization sequence is specified
by the standard in such a case or if I cannot rely on the
initialization sequence even when everything is in the same translation
unit?

section 3.6.2
The storage for objects with static storage duration shall be zero
initialized before any other initilization takes place


ok, but in my case, both variables are explicitly initialized to
non-zero values.

That shouldn't change the result of when that member is initialized.
I was just pointing out that the above section indicates that
initialization takes place before those variables having other storage
durations. I'm trying to explain what the standard says in sequence.
3.6.2 is about static storage duration.



section 3.7.1 says
The keyword static applied to a class data member in a class
definition gives the data member static storage duration.
(does not cover those static members in a namespace scope!)


What I really like to know is if I usually could rely on having
my global variables being initialized in the same sequence as
they appear in the source code, i.e. whether the old gcc-2.95
compiler is buggy because it initializes d _before_ t or if this
is an implementation detail that is not defined by the standard.

3.7.1 says that a static member, as long as its not in a namespace,
has static storage duration.
The standard therefore guarentees that the static member is treated as
in 3.6.2, so gcc-2.95 appears to be non-compliant in that respect.
I'ld suggest that its not something that is implementation defined.
.
User: "Christof Warlich"

Title: Re: initialization sequence issue 06 Jan 2008 01:32:11 AM
Salt_Peter schrieb:

The standard therefore guarentees that the static member is treated as
in 3.6.2, so gcc-2.95 appears to be non-compliant in that respect.
I'ld suggest that its not something that is implementation defined.

Thanks a lot for this precise answer, it will help me to convince my
colleagues from the build-team that their (hand-made) way of collecting
static ctors is not according to the standard.
.




User: "James Kanze"

Title: Re: initialization sequence issue 06 Jan 2008 08:06:17 AM
On Jan 5, 7:17 pm, Christof Warlich <cwarl...@gmx.de> wrote:

the few lines of code below show different results depending on
the compiler version (gcc-2.95 versus gcc-3.3 and later):
gcc-2.95 first initializes d (line 9) and then t (line 8), as
running the executable yields
initialized d
X constructor
whereas gcc-3.3 and later gcc versions do as I'd expect: They
initialize the variables as they appear in the source code:
X constructor
initialized d

I'm not sure I'd have any expectations about this. Line 8
doesn't define anything.

Could anyone tell if the initialization sequence is specified
by the standard in such a case or if I cannot rely on the
initialization sequence even when everything is in the same translation
unit?

The standard guarantees that object definitions requiring
dynamic initialization occur in the order of the definitions
within a given translation unit. Note, however, that a static
member of a template is only "defined" if it is
instantiated---each instantiation is a separate definition (and
the template definition is *not* a definition of an object).
Because the point of instantiation will vary if the static
member is instantiated in several different translation units,
the standard simply says that the order in this case is
unspecified.

1 #include <stdio.h>
2 struct X {
3 X() {printf("X constructor\n");}
4 };
5 template<typename T> struct A {
6 static T t;
7 };
8 template<typename T> T A<T>::t;

Note that the above is a declaration, not a definition.

9 X &x =3D A<X>::t;
10 int d =3D printf("initialized d\n");
11 int main() {}

Just curious, but what do you expect to happen if A<X>::t is
also implicitely initialized in another translation unit?
I think you've got a case of unspecified behavior here.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34
.
User: "Christof Warlich"

Title: Re: initialization sequence issue 06 Jan 2008 11:45:39 AM
James Kanze schrieb:

The standard guarantees that object definitions requiring
dynamic initialization occur in the order of the definitions
within a given translation unit. Note, however, that a static
member of a template is only "defined" if it is
instantiated---each instantiation is a separate definition (and
the template definition is *not* a definition of an object).
Because the point of instantiation will vary if the static
member is instantiated in several different translation units,
the standard simply says that the order in this case is
unspecified.

1 #include <stdio.h>
2 struct X {
3 X() {printf("X constructor\n");}
4 };
5 template<typename T> struct A {
6 static T t;
7 };
8 template<typename T> T A<T>::t;


Note that the above is a declaration, not a definition.

You are right, this is a declaration. And my initial posting was
off by one line: I meant to talk about lines 9 and 10 respectively,
which _are_ both definitions.
But anyway, as I introduced line 9 only to instantiate the template
to run the X constructor, it should be replaced by
template struct A<X>;
But anyway, the result is still the same with the two compiler
versions.


9 X &x = A<X>::t;
10 int d = printf("initialized d\n");
11 int main() {}


Just curious, but what do you expect to happen if A<X>::t is
also implicitely initialized in another translation unit?

Well, this is an interesting question, as I was paying arround with this
just exactly because I intentionally wanted to instantiate it within
other translation units: When I do this, the linker seems to silently
through away all instantiations but the very first it finds in any of
the translation units that it links. Thus, this (together with the
improvement that I've described above) seems to be a method to _define_
variables in header files, even if they are included into multiple
translation units. This may be useful for libraries like the STL that
entirely live in header files, as it allows to work around the need
for a separate translation unit just because the library needs some
global variables. I'd be very interested to get some feedback on this
idea!

I think you've got a case of unspecified behavior here.

Well, as I said, lines 9 and 10 are the ones of interest, with line
9 replaced as suggested above. And I still hope that the sequence of
these lines define the sequence of construction of the related variables.


--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

.
User: "James Kanze"

Title: Re: initialization sequence issue 07 Jan 2008 05:17:18 AM
On Jan 6, 6:45 pm, Christof Warlich <cwarl...@gmx.de> wrote:

James Kanze schrieb:

The standard guarantees that object definitions requiring
dynamic initialization occur in the order of the definitions
within a given translation unit. Note, however, that a static
member of a template is only "defined" if it is
instantiated---each instantiation is a separate definition (and
the template definition is *not* a definition of an object).
Because the point of instantiation will vary if the static
member is instantiated in several different translation units,
the standard simply says that the order in this case is
unspecified.

1 #include <stdio.h>
2 struct X {
3 X() {printf("X constructor\n");}
4 };
5 template<typename T> struct A {
6 static T t;
7 };
8 template<typename T> T A<T>::t;

Note that the above is a declaration, not a definition.

You are right, this is a declaration. And my initial posting was
off by one line: I meant to talk about lines 9 and 10 respectively,
which _are_ both definitions.
But anyway, as I introduced line 9 only to instantiate the template
to run the X constructor, it should be replaced by
template struct A<X>;

Which I don't think changes anything.

But anyway, the result is still the same with the two compiler
versions.

9 X &x =3D A<X>::t;
10 int d =3D printf("initialized d\n");
11 int main() {}

Just curious, but what do you expect to happen if A<X>::t is
also implicitely initialized in another translation unit?

Well, this is an interesting question, as I was paying arround
with this just exactly because I intentionally wanted to
instantiate it within other translation units: When I do this,
the linker seems to silently through away all instantiations
but the very first it finds in any of the translation units
that it links.

Well, it obviously has to throw away all but one. Which one is
unspecified.

Thus, this (together with the improvement that I've described
above) seems to be a method to _define_ variables in header
files, even if they are included into multiple translation
units.

It could be. But it raises the problem you're complaining
about: the variable is defined in many different translation
units, so its order of initialization with respect to any one
translation unit is unspecified.

This may be useful for libraries like the STL that entirely
live in header files, as it allows to work around the need for
a separate translation unit just because the library needs
some global variables. I'd be very interested to get some
feedback on this idea!> I think you've got a case of
unspecified behavior here.

I believe that Matt Austern used a similar trick at some time,
precisely to enable a library to be delivered as header files
only.
The order of initialization is unspecified. The rest of the
behavior is well defined. When using such a trick, I would
strongly recommend ensuring that the initialization is static.

Well, as I said, lines 9 and 10 are the ones of interest, with
line 9 replaced as suggested above. And I still hope that the
sequence of these lines define the sequence of construction of
the related variables.

They impose the order of initialization of x and d: you can be
assured that x is initialized to refer to A<X>::t before the
initializer of d is called. You have no guarantee, however,
that A<X>::t has been constructed; as a template instantiation,
the order of initialization is unspecified. You end up with
something more or less like:
extern int a ;
int& b =3D a ;
int c =3D (std::cout << "initialized c" << std::endl, b ) ;
Initializing a reference does not guarantee that what it refers
to is already initialized.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34
.




  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.1232     pg.940     pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER