This is GCC Bugzilla
This is GCC Bugzilla Version 2.20+
View Bug Activity | Format For Printing | Clone This Bug
When compiling the attached file (56 lines) with > g++ FehlerInit.cpp and running it I get > ./a.out -33630626 Speicherzugriffsfehler The first line in main LitIntOccInt::Var v; yields a call of the member function InfoPolicyVector<int>::new_variable() which prints out the iterator difference between centre and info_vector.begin(), where centre is a static data member initialised to info_vector.begin(), and thus the result should be 0, but as shown above, it is "undefined". The code given seems to be a minimal example (up to some typedefs) in the sense, that removing any other stuff (which seems completely unrelated to the above behaviour) changes the output to the correct "0". Release: gcc 3.2.1 Environment: > g++ -v Reading specs from /compsci/partition1/csoliver/GCC/gcc-3.2.1/lib/gcc-lib/i686-pc-linux-gnu/3.2.1/specs Configured with: /compsci/partition1/csoliver/GCC/gcc-3.2.1/configure --enable-threads=posix --enable-long-long --prefix=/compsci/partition1/csoliver/GCC/gcc-3.2.1 --with-local-prefix=/compsci/partition1/csoliver/GCC/Include_3.2.1 --enable-languages=c,c++ --disable-nls --enable-shared Thread model: posix gcc version 3.2.1 How-To-Repeat: Compile and run.
Fix: I have no idea. It seems to me quite serious. P.S. Perhaps it would be a good idea to somehow improve the instructions for submitting a bug. For example I couldn't find an explanation of what the above abbreviations for the error class could mean.
From: "Giovanni Bajo" <giovannibajo@libero.it> To: <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <nobody@gcc.gnu.org>, <O.Kullmann@Swansea.ac.uk>, <gcc-prs@gcc.gnu.org> Cc: Subject: Re: c++/10112: static data member is not correctly initialised Date: Sun, 16 Mar 2003 23:22:30 +0100 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&p r=10112 Confirmed with 3.2, cygwin on x86. Reduced snippet is: ---------------------------------- #include <cassert> using namespace std; struct A { int p; A(int _p) : p(_p) {} }; template <typename T> struct B { static A a; static int p1; }; template <typename T> A B<T>::a(123); template <typename T> int B<T>::p1 = a.p; int main() { // Should not assert, but it does assert(B<int>::p1 == B<int>::a.p); } ---------------------------------- Looking at the generated code on x86, it seems that the two variables are initialized in reversed order: 00401104 <__Z41__static_initialization_and_destruction_0ii>: [....] 401139: a1 b0 e8 40 00 mov 0x40e8b0,%eax 40113e: a3 a0 e8 40 00 mov %eax,0x40e8a0 [....] 401172: c7 04 24 b0 e8 40 00 movl $0x40e8b0,(%esp,1) 401179: c7 44 24 04 7b 00 00 movl $0x7b,0x4(%esp,1) 401180: 00 401181: e8 9a 47 00 00 call 405920 <__ZN1AC1Ei> 00405920 <__ZN1AC1Ei>: 405920: 55 push %ebp 405921: 89 e5 mov %esp,%ebp 405923: 8b 55 08 mov 0x8(%ebp),%edx 405926: 8b 45 0c mov 0xc(%ebp),%eax 405929: 89 02 mov %eax,(%edx) 40592b: 5d pop %ebp 40592c: c3 ret The code at 401139 copies B<T>::a.p into B<T>::p1 (it's the initialization of B<T>::p1), while the second block initializes B<T>::a.p with 123 (0x7b), but it's too late. I tried with no optimization, and -O0/1/2/3 and there is no difference, the code is always wrong. As for the standard, §9.4.2p7 says <<Static data members are initialized and destroyed exactly like nonlocal objects (3.6.2, 3.6.3).>>. §3.6.2p1 says: <<Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place. Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.>>. Now, B<T>::p1 is a POD type but it is not initialized with a constant expression, so I don't see any reason why it should be initialized before B<T>::a. Giovanni Bajo
State-Changed-From-To: open->analyzed State-Changed-Why: the ordering of these two template instantiations is implementation defined. I think there's an algorithm to get the order right nathan
From: Wolfgang Bangerth <bangerth@ticam.utexas.edu> To: giovannibajo@libero.it, <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <o.kullmann@swansea.ac.uk>, <nathan@gcc.gnu.org> Cc: Subject: Re: c++/10112: static data member is not correctly initialized Date: Mon, 17 Mar 2003 18:15:06 -0600 (CST) I think with this code, A::p1 is statically initialized (being a POD type), while B::a is dynamically initialized (having a user-defined constructor). I think I remember that the standard specifies that static initializers always run before dynamic ones, irrespective of the order in which they appear in the source file. In that case, this would not be a bug. W. ------------------------------------------------------------------------- Wolfgang Bangerth email: bangerth@ticam.utexas.edu www: http://www.ticam.utexas.edu/~bangerth/
From: Oliver Kullmann <O.Kullmann@Swansea.ac.uk> To: nathan@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org, nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org Cc: Subject: Re: c++/10112: static data member is not correctly initialised Date: Mon, 17 Mar 2003 18:49:06 +0000 On Mon, Mar 17, 2003 at 12:04:17PM -0000, nathan@gcc.gnu.org wrote: > Date: 17 Mar 2003 12:04:17 -0000 > To: O.Kullmann@Swansea.ac.uk, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org, > nobody@gcc.gnu.org > From: nathan@gcc.gnu.org > Reply-To: nathan@gcc.gnu.org, O.Kullmann@Swansea.ac.uk, gcc-bugs@gcc.gnu.org, > gcc-prs@gcc.gnu.org, nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org > X-Mailer: gnatsweb 2.9.3 > Subject: Re: c++/10112: static data member is not correctly initialised > X-Spam-Status: No, hits=-99.3 required=8.0 > tests=NO_REAL_NAME,USER_IN_WHITELIST > version=2.50 > X-Spam-Level: > X-Spam-Checker-Version: SpamAssassin 2.50 (1.173-2003-02-20-exp) > > Synopsis: static data member is not correctly initialised > > State-Changed-From-To: open->analyzed > State-Changed-By: nathan > State-Changed-When: Mon Mar 17 12:04:17 2003 > State-Changed-Why: > the ordering of these two template instantiations is implementation defined. I think there's an algorithm to get > the order right > > nathan > > http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=10112 Hi, (I hope that's the right way to reply?!) hmhm, might be. I guess the relevant sentence is in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist. (section 14.7.1 of ISO/IEC 14882:1998(E)), and thus one could conclude that in Giovanni's example in the instruction assert(B<int>::p1 == B<int>::a.p); the order of initialisations depends on the order of evaluation of the equality expression, which is implementation defined. Is this the interpretation?! The best solution (which might also be a better design) seems to me, to put the static data member (in the example, of class B) into a new (local) class X (or struct), for which we provide a constructor guaranteeing the right order of initialisation. The host class B then has one static data member of type X. When we first use this data member, it will be constructed using the right order of initialisation. Sounds okay to me. (Worked in my case.) Thanks for your help! Oliver -- Dr. Oliver Kullmann Computer Science Department University of Wales Swansea Faraday Building, Singleton Park Swansea SA2 8PP, UK http://cs-svr1.swan.ac.uk/~csoliver/
From: "Giovanni Bajo" <giovannibajo@libero.it> To: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu>, <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <o.kullmann@swansea.ac.uk>, <nathan@gcc.gnu.org> Cc: Subject: Re: c++/10112: static data member is not correctly initialized Date: Tue, 18 Mar 2003 02:36:55 +0100 ----- Original Message ----- From: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu> To: <giovannibajo@libero.it>; <gcc-gnats@gcc.gnu.org>; <gcc-bugs@gcc.gnu.org>; <o.kullmann@swansea.ac.uk>; <nathan@gcc.gnu.org> Sent: Tuesday, March 18, 2003 1:15 AM Subject: Re: c++/10112: static data member is not correctly initialized Wolfgang, objects of POD types are statically initiliazed if and only if the initiliazer is constant, and that's not the case of the above snippet. This is very clear in §3.6.2p1, which I quoted (it's the same paragraph that introduces the concept of "static initialization" and "dynamic initalization"). Since my quote was maybe confusing because stripped down to the minimum, I post the full paragraph: ------------------- The storage for objects with static storage duration (3.7.1) shall be zeroinitialized (8.5) before any other initialization takes place. Zeroinitialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place. Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit. ------------------- It seems clear to me that A::p1 cannot be statically initialized, and thus must follow the order of definition. Oliver, I think you are misreading the standard. If you de-legalise 14.7.1, it basically says that the compiler must generate code only for template (member) functions that are really used in the code. For completeness, it also says that static data members must be intialized only if they are really used, but it does not say in any way that initialization must be done WHEN the member is effectively used. In fact, all the initialization of static data members and non-local objects (like global static variables) must be done before main(), like §3.6.2 explains. Nathan, I agree that the order of instantiation is implementation defined, but the initialization of the static data members should happen before any template is instantiated. §14.7.1p8 decouples initialization of static data members and instantiation of class templates, saying that <<implicit instantiation of a class template does not cause any static data members of that class to be implicitly instantiated>>. In fact, <<static data members are initialized [...] exactly like nonlocal objects>> (§9.4.2p7), <<before any other initialization takes place>> (§3.6.2p1) (and of course only if <<the static data member is itself used in a way that requires the definition of the static data member to exist>> (§14.7.1p1). In the end, I believe that this is a bug in GCC, and other compilers (VC 7.1, Comeau 4.3.0) seem to agree. Giovanni Bajo
From: Gabriel Dos Reis <gdr@integrable-solutions.net> To: "Giovanni Bajo" <giovannibajo@libero.it> Cc: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu>, <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <o.kullmann@swansea.ac.uk>, <nathan@gcc.gnu.org> Subject: Re: c++/10112: static data member is not correctly initialized Date: 18 Mar 2003 02:46:40 +0100 "Giovanni Bajo" <giovannibajo@libero.it> writes: [...] | Nathan, I agree that the order of instantiation is implementation defined, | but the initialization of the static data members should happen before any | template is instantiated. From which parts of the standard did read that? | =A714.7.1p8 decouples initialization of static data | members and instantiation of class templates, saying that <<implicit | instantiation of a class template does not cause any static data members = of | that class to be implicitly instantiated>>. In fact, <<static data members | are initialized [...] exactly like nonlocal objects>> (=A79.4.2p7), <<bef= ore | any other initialization takes place>> (=A73.6.2p1) (and of course only if | <<the static data member is itself used in a way that requires the | definition of the static data member to exist>> (=A714.7.1p1). I can't read that to imply the your first assertion quoted above. -- Gaby
From: "Giovanni Bajo" <giovannibajo@libero.it> To: "Gabriel Dos Reis" <gdr@integrable-solutions.net> Cc: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu>, <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <o.kullmann@swansea.ac.uk>, <nathan@gcc.gnu.org> Subject: Re: c++/10112: static data member is not correctly initialized Date: Tue, 18 Mar 2003 03:01:11 +0100 ----- Original Message ----- From: "Gabriel Dos Reis" <gdr@integrable-solutions.net> To: "Giovanni Bajo" <giovannibajo@libero.it> Cc: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu>; <gcc-gnats@gcc.gnu.org>; <gcc-bugs@gcc.gnu.org>; <o.kullmann@swansea.ac.uk>; <nathan@gcc.gnu.org> Sent: Tuesday, March 18, 2003 2:46 AM Subject: Re: c++/10112: static data member is not correctly initialized >From which parts of the standard did read that? I was reading §3.6.2p1 <<before any other initialization takes place>> in this way. Anyway, the bug is about the order of initialization between two static data members. Since instantiation of class templates does not affect initialization of static data members (as per quoted paragraph), even if you instantiate the class templates before inizializing the data members, you should respect the order of inizialization of the data members. It seems to me that GCC is initializing the static data members because the templates are instantiated, but this violates §14.7.1p8. Giovanni Bajo
From: Gabriel Dos Reis <gdr@integrable-solutions.net> To: "Giovanni Bajo" <giovannibajo@libero.it> Cc: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu>, <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <o.kullmann@swansea.ac.uk>, <nathan@gcc.gnu.org> Subject: Re: c++/10112: static data member is not correctly initialized Date: 18 Mar 2003 03:34:23 +0100 "Giovanni Bajo" <giovannibajo@libero.it> writes: | ----- Original Message ----- | From: "Gabriel Dos Reis" <gdr@integrable-solutions.net> | To: "Giovanni Bajo" <giovannibajo@libero.it> | Cc: "Wolfgang Bangerth" <bangerth@ticam.utexas.edu>; | <gcc-gnats@gcc.gnu.org>; <gcc-bugs@gcc.gnu.org>; <o.kullmann@swansea.ac.u= k>; | <nathan@gcc.gnu.org> | Sent: Tuesday, March 18, 2003 2:46 AM | Subject: Re: c++/10112: static data member is not correctly initialized |=20 |=20 | >From which parts of the standard did read that? |=20 | I was reading =A73.6.2p1 <<before any other initialization takes place>> = in | this way. That paragraph speaks about initialisation of objects. It says nothing about the order of template instantiations and the order | Anyway, the bug is about the order of initialization between two static d= ata | members. Since instantiation of class templates does not affect | initialization of static data members (as per quoted paragraph), even if = you | instantiate the class templates before inizializing the data members, you | should respect the order of inizialization of the data members. Unless the instantiation of the class template uses the static data members.=20 | It seems to me that GCC is initializing the static data members because t= he | templates are instantiated, but this violates =A714.7.1p8. What you're missing is that your expression in the assertion introduces an indeterminism in the order of instantiation. It is the instantiation of the static data members that defines them, not just their mere -template- definition. What is happening is not far from the following scenario:=20 struct A {=20 int p; =20 A(int x) : p(x) { } };=20 struct B { static A a; static int p1; }; int B::p1 =3D a.p; A B::a(123); int main() { assert (B::a.p =3D=3D B::p1); }=20 -- Gaby
*** Bug 11733 has been marked as a duplicate of this bug. ***
*** Bug 13915 has been marked as a duplicate of this bug. ***
*** Bug 14102 has been marked as a duplicate of this bug. ***
*** Bug 17910 has been marked as a duplicate of this bug. ***
This PR has a long and wicked history. Presumably, PR 17910 is a duplicate so if anyone considers fixing this PR, she may as well go there first as PR 17910 has a very nice and small testcase. W.
It's not clear to me that there's anything to be fixed; the reduced testcase in this PR works, and the testcase for 17910 seems to work the way the point of instantiation rules say it ought to. And people can always use explicit instantiation directives to control order of initialization.