Re: [boost] [pool] segfault (fun with static initialization ordering)

________________________________________ De: boost-bounces@lists.boost.org [boost-bounces@lists.boost.org] En nombre de JOAQUIN M. LOPEZ MUÑOZ [joaquin@tid.es] Enviado el: viernes, 11 de julio de 2008 17:35 Para: boost@lists.boost.org 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
participants (1)
-
JOAQUIN M. LOPEZ MUÑOZ