Topic: static initialization of local statics


Author: "frege" <gottlobfrege@gmail.com>
Date: Thu, 30 Nov 2006 13:25:34 CST
Raw View
So, GLOBAL statics are zero-initialized first (typically by the OS or
compiler), even before dynamic initialization of globals.

But what about function-local statics?  When does the zero-init occur?

The standard (6.7.4) says:

   "The zero-initialization (8.5) of all local objects with static
storage duration (3.7.1) is performed before any other initialization
takes place."

"any other initialization" is, to me, ambiguous.  Does it mean other
initializations of this object, or non-zero initializations of other
objects?
The very next sentence is:

   "A local object of POD type (3.9) with static storage duration
initialized with constant-expressions is initialized before its block
is first entered"

Since the first sentence doesn't mention "before its block is first
entered", I'm hoping it means WAY earlier - ie at the same time as
global static zero-init.

Anyone know?  If it is indeed ambiguous, does anyone know what most/all
compilers do?  I suspect they zero-int at the same time as globals, but
it would be nice to be sure.

And lastly, I should mention that this is particularly important for
threads, which, so far, the standard says nothing about.  Consider:

int func()
{
   bool flag;

   if (AtomicCompareAndSet(flag, 0, 1))
   {
      // truly first time here...
   }
}

1. if static-local is zero-initted at program load - the code works.
2. if static-local is zero-initted 'before its block is first entered'
- then the compiler might actually zero init 'flag' the first time the
block is entered - ***in each thread***, so the code doesn't work.

Any idea how this is expected to play out if/when threads are added to
the standard?

Also, note, from the second sentence above-quoted from the standard,
that things like:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

don't necessarily work as static-locals either.

Help!

P.S. Yes, I understand that moving the local to a global would solve
this particular problem, but that gets hard for template functions.
(And yes statics and their construct/destruct times are evil in general
and should be avoided.)


Tony

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Frederick Gotham <fgothamNO@SPAM.com>
Date: Thu, 30 Nov 2006 13:55:38 CST
Raw View
frege:

> But what about function-local statics?  When does the zero-init occur?
>
> The standard (6.7.4) says:
>
>    "The zero-initialization (8.5) of all local objects with static
> storage duration (3.7.1) is performed before any other initialization
> takes place."


The implementation may choose to set the static object's bits at any time,
just so long as the program behaves as if the static object is initialised
the first time and only the first time the function is called. In this
respect, the following two snippets are similar:

    void Func()
    {
        static MyClass obj;
    }


and:

    bool first_time = true;

    void Func()
    {
        static storage_for<MyClass> mem;

        if (first_time)
        {
            ::new((void*)&mem) MyClass();

            atexit( mem.~MyClass ); /* Let's pretend this is OK! */

            first_time = false;
        }
    }

--

Frederick Gotham

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Gianni Mariani <gi3nospam@mariani.ws>
Date: Thu, 30 Nov 2006 14:16:42 CST
Raw View
frege wrote:
.
> Anyone know?  If it is indeed ambiguous, does anyone know what most/all
> compilers do?  I suspect they zero-int at the same time as globals, but
> it would be nice to be sure.
>
> And lastly, I should mention that this is particularly important for
> threads, which, so far, the standard says nothing about.  Consider:
>
> int func()
> {
>    bool flag;
>
>    if (AtomicCompareAndSet(flag, 0, 1))
>    {
>       // truly first time here...
>    }
> }
>
> 1. if static-local is zero-initted at program load - the code works.
> 2. if static-local is zero-initted 'before its block is first entered'
> - then the compiler might actually zero init 'flag' the first time the
> block is entered - ***in each thread***, so the code doesn't work.
>
> Any idea how this is expected to play out if/when threads are added to
> the standard?

Since this deals with threads, there is no standard answer.  You have to
check it and see each implementation you use.

GCC (I think versions 4.*) already make sure that local statics are
initialized once even in a threaded environment. This is a case where
the compiler does the work for you.

As for your example above, you're probably going to need more than 2 states:

int func()
{
     {
         static atomic<int> state;

 ... stuff ...

         ... initialize and wake up other waiting threads when done ...
         ... wait for initialization happening in other thread to finish
         ... pop right through initialization is complete ...
     }
}

I don't remember the rest of it but I do remember it to the programmer a
few days to get it right.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: pete@versatilecoding.com (Pete Becker)
Date: Thu, 30 Nov 2006 20:35:31 GMT
Raw View
frege wrote:

>    "A local object of POD type (3.9) with static storage duration
> initialized with constant-expressions is initialized before its block
> is first entered"
>
> Since the first sentence doesn't mention "before its block is first
> entered", I'm hoping it means WAY earlier - ie at the same time as
> global static zero-init.

Since you can't write well-formed code that can detect whether the
initialization happens WAY earlier, there's no requirement that it do
so. "Before" just means "before."

>
> And lastly, I should mention that this is particularly important for
> threads, which, so far, the standard says nothing about.

That is, you're trying to reason about what the standard requires in an
area where it imposes no requirements. That's not going to get you very
far. <g> You'll have to check your compiler's documentation to see what,
if anything, it promises here.

> Any idea how this is expected to play out if/when threads are added to
> the standard?
>

It will do something sensible. Requirements for initializers are tricky,
and still being worked out.

--

 -- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]