Any interested GCC maintainers/contributors:

I have a suggestion for GCC to eliminate a pernicious problem - that of 
automatically initialising static (i.e. long-lived) variables in the correct 
order based on mutual dependencies, apparently not normally addressed by 
compilers.  This is a thorny issue, and is normally discovered the hard way 
by most programmers - not the way to produce robust code.  I would welcome 
any correspondence/queries on the matter.

The suggestion is for a simple modification to GCC to ensure that static 
variables are always initialised (and destroyed) in the correct order 
determined by dependencies between the actual variables concerned - this 
applies to both C and C++.  Someone may already have tackled this issue, 
though I don't see it on the GNU site.  I would be happy to supply example 
code to illustrate the concept to any interested person.

I have a very simple approach to
   (a) ensure that every static variable used in initialising another is 
always initialised beforehand, even when this dependency is hidden from the 
compiler, and
   (b) detect (unfortunately not at compile time) when correct 
initialisation is impossible due to a cyclic dependency.

A more involved mechanism can also
   (c) ensure that no static variable is destroyed before its last use.

The essence of the idea for (a) is:
   - Access each static variable including static class members via 
(inlined) wrapper code in the same way as is typical for function-local 
variables (i.e. initialised once on first access using a flag).  This 
ensures that every static variable gets initialised before use, especially 
where such use is in the initialisation of another static variable.
   - Retain initialisation of static variables before calling main() (via 
the wrapper code).  This ensures that initialisation always occurs before 
main() is called as would be expected, and does so in a single-threaded 
environment, eliminating any need for a mutex.
   - Preferably initialise all function-local variables at this point too - 
initialisation in a multi-threaded environment using a simple flag (as 
opposed to a mutex) is non-reentrant, and can fail sporadically.  This 
modification would have the effect that function-local statics will always 
be initialised before calling main() even if never used.  The alternative is 
to use a mutex, which may be problematic (OS-dependent).
   - I would avoid the approach apparently taken in C# and Java - that of 
initialising all statics in each class as a set (this is not as robust, 
since references between classes may be cyclic without cyclic dependencies 
for initialisation.  Note that this means that statics in a class may be 
initialised after the first instances of the class are constructed, unless 
used by the constructor.

The approach taken for (b) is to have an intermediate state for the flag 
indicating that the initialisation of a given variable is in progress but 
not yet complete.  If the initialisation is triggered a second time in this 
state, a cyclic dependency exists.

The approach for (c) involves triggering initialisation of every object with 
a destructor early enough that the "atexit" call to the destructor occurs 
after that of every object that has methods that accesses it.  This can be 
dealt with separately, and I will omit the detail for now.

Note that these changes are probably largely ANSI-compliant, and as such may 
not have to be treated as an extension.  When applied to global ("extern") 
variables, additional linker information is needed (a reference to the flag 
and initialisation code).  This will introduce problems when linking code 
generated by different versions of the compiler.

Manfred von Willich 

Reply via email to