From: nagle@netcom.com (John Nagle)
Subject: Re: Static global initialization outside of main() legal?
Organization: Netcom - Online Communication Services  (408 241-9760 guest) 
Date: Thu, 31 Dec 1992 19:11:23 GMT

wlee@sales.GBA.NYU.EDU (Wai-Shing Lee) writes:
>   I want to initialize a static global at run-time but I don't want to
>have to have a programmer using my modules to have to call some init() funciton
>at the begining of thier main().

>I've traced it and sure enough makepointer() is called and pointer is assigned
>a value before main() even starts.  Is the portable, legal.  I didn't look
>to hard in my C++ book, but there weren't any obvious answers.  Is this
>C++, C or something I should stay away from?

       You're working in a very messy area of C++.  The order in which
things happen during static initialization isn't the same in different
compilers.  The language rules arein section r3.4 of "The C++ Programming
Language, Second Edition", and you should read them if you want to do this
sort of thing.

       In most implementations, static initializers are run before
"main" is called.  For initializers that don't call functions, this
is enough to get the static variables initialized properly.  But
initializers that call functions can create serious problems, especially
if the functions have side effects, are in a different compilation unit
(file), or depend on other static variables being initialized.  The order
in which things get initialized varies from compiler to compiler and
sometimes from compile to compile, so you can't depend on this at all.

       If you use C++ classes, it gets worse.

       Constructors are functions.  So static variables declared with
a type that has a constructor result in the class constructor function
being called before startup.  But you're not guaranteed that the static
variables of the class implementing the constructor were initialized 
before the first use of the class.  So it is bad C++ to write a class
which needs static initialization (other than to 0, which is special
and must occur before any code can run) before its constructors can be
validly called.

       It's also worth noting that in many implementations, you can't
print anything before "main" is called, so printing messages in a 
constructor may cause problems if the constructor is used to initialize
a static variable.

       Does anyone know what happens if you raise an exception in a 
constructor called during static initialization?  The reference manual
is silent on the subject.

       Modula 2 has a much better approach to initialization.  They
have the linker sort out the dependency structure, based on the call
graph.  The linker finds an order that will result in the initializers
being called in a valid order, so everything gets initialized before
it can be called.  If the linker can't find a valid order, you get an error
message at link time.  (TopSpeed Modula II is an example of a system that
supports this properly.)  In fact, the need for a "main program" disappears;
it's just another initialization section.  (Nice for programs where the
"main program" is an event loop that comes from a library.)  This is 
clearly the right way to do it, but C++, as a bolt-on to existing C 
compilers, can't do it that way, because it requires support in the linker.  

       So, unless you want to worry about all this stuff, calling functions
with side effects in initializers should be avoided.

					John Nagle
Xref: sparky comp.lang.c++:18539 comp.lang.c:19024