|
Boost : |
From: JOAQUIN M. LOPEZ MUÑOZ (joaquin_at_[hidden])
Date: 2008-07-12 06:35:40
________________________________________
De: boost-bounces_at_[hidden] [boost-bounces_at_[hidden]] En nombre de JOAQUIN M. LOPEZ MUÑOZ [joaquin_at_[hidden]]
Enviado el: viernes, 11 de julio de 2008 17:35
Para: boost_at_[hidden]
Asunto: Re: [boost] [pool] segfault (fun with static initialization ordering)
_______________________________________
> The following is a case where the precende rule *cannot* be applied
> for logical reasons:
>
> template<typename T>
> struct foo{
> static int x;
> };
>
> template<typename T>
> int foo<T>::x=T::x;
>
> struct bar
> {
> static int x;
> };
>
> int bar::x=666;
>
> static int x=foo<bar>::x;
Please disregard this example, it is flawed because bar::x is statically initialized
an because ultimately the compiler is not required to perform the dependency
analysis suggested above. I've been playing with the following:
#include <iostream>
#if defined(CASE1)
struct bar{static int x;};
static int f(){return 666;}
int bar::x=f();
template<typename T>struct foo{static int x;};
template<typename T>int foo<T>::x=T::x;
#elif defined(CASE2)
template<typename T>struct foo{static int x;};
template<typename T>int foo<T>::x=T::x;
struct bar{static int x;};
static int f(){return 666;}
int bar::x=f();
#endif
int main()
{
std::cout<<"bar::x: "<<bar::x<<std::endl;
std::cout<<"foo<bar>::x: "<<foo<bar>::x<<std::endl;
}
Using GCC in Cygwin the output is the same for both CASE1 and CASE2:
bar::x: 666
foo<bar>::x: 666
Using MSVC++ 8.0 I observed a light-shedding behavior: When compiling with a
fresh project, the output is the same for CASE1 and CASE2 and coincides with
GCC:
bar::x: 666
foo<bar>::x: 666
But after that I changed the code to the following:
#elif defined(CASE2)
template<typename T>struct foo{static int x;};
template<typename T>int foo<T>::x=T::x;
struct bar{static int x;};
static int x=foo<bar>::x; // NEW LINE
static int f(){return 666;}
int bar::x=f();
#endif
This forces foo<bar>::x evaluation to be done at a prior monent and the
result is (for CASE2):
bar::x: 666
foo<bar>::x: 0
Now, the funny thing is that if I revert to the original code (i.e. I delete
the line comented as // NEW LINE) then MSVC++ 8.0 outputs the following
both for CASE1 and CASE2
bar::x: 666
foo<bar>::x: 0
which is different than my early runs! The compiler seems to reuse some
intermediate files from prior compilations that set a particular initialization
order: confirming this hypothesis, if I clean the project and rebuild again then
we're back at the original output for both CASE1 and CASE2:
bar::x: 666
foo<bar>::x: 666
So, you see how one cannot actually rely on any particular initialization
order for class template statis data. The standard explicitly leaves this
initialization order unspecified (see the rest of 3.6.2).
With respect to the rest of my previous post I maintain the explanation for
the problem with pool you're having and contend that referring to
singleton_pool<...> inside fast_pool_allocators ctors is the proper fix.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk