> Lots of real C++ code is order-sensitive.  This is a serious problem and
> there are a couple of ugly solutions to it.  

I'd say that the best solution would be to get rid of globals. This is
actually very easy:

If you have

TYPE VAR = INITIALIZER;

replace that with

TYPE& getVAR(){
  static TYPE obj = INITIALIZER;
  return obj;
}

Then use getVAR() whereever you've used VAR before. For backwards
compatibility, you can even do

#define VAR (getVAR())

In understand that modules don't share global objects (perhaps except
for the module singleton), so removing global should be a local change
inside each module only.

> To get the calling order right.  CLN consists of >800 source-code
> modules and uses a bridge pattern to abstract the actual
> implementation away from the interface.

In cln-1.1.2.orig, there are 864 .cc files inside src, but only 43 of
them use CL_PROVIDE. So I think changing those modules is a much
smaller change than you may anticipate.

> The best solution would be to teach the linker about it.

The linker actually does know about constructor order. In g++, there
is a guarantee that object files within the same executable or shared
library are initialized from right to left, in the order in which the
objects appear on the linker line.

> The solution we are talking about here is just a rather
> unconventional but beautiful one.

Looking at the code in module.h, I'd question that there is anything
beautiful about it.

> Rather than that or changing the module ordering macros and writing
> autoconf scripts to see if the global dtors are making use of
> cxa-atexit I guess I'll just switch on -fno-use-cxa-atexit in CLN
> whenever GCC-3.x is used.  Hope this'll work for a couple of
> years...

I very much doubt that. Somebody will notice that the _GLOBAL__
symbols don't need unique names at all, since they are not global (in
fact, static_initialization_and_destruction is already in gcc 2.95 a
single function for both ctors and dtors, so it is questionable
whether these "clever" macros really get the control flow right).

Furthermore, the C++ ABI really specifies that the .init and .fini
sections shouldn't be used for constructors and destructors. For
constructors, .initarray should be used, to allow portable integration
of constructors across different compilers. Destructor sections should
not be used, instead, cxa_atexit won't be an option at some time in
the future.

Regards,
Martin


Reply via email to