Wrong order of shared static dtors

Marco Leise via Digitalmars-d digitalmars-d at puremagic.com
Tue Nov 11 02:43:46 PST 2014


Am Mon, 10 Nov 2014 10:06:01 -0500
schrieb Steven Schveighoffer <schveiguy at yahoo.com>:

> I don't know about your specific issue. But I do know how the runtime 
> calls static ctors/dtors because I rewrote that part a few years ago.
> 
> First, any ctors/dtors in a specific module are called in the order they 
> appear in the file.
> 
> Second, the compiler records 3 things about a module:
> 1. Is it a standalone module? That is, does it not import any other modules.
> 2. If not, what modules does it import.
> 3. Does it have any dtors or ctors (it has a flag for each kind)
> 
> When run, the runtime uses this information to build a graph of the 
> ordering to call the static ctors. If it detects any cycles in that 
> graph, where module A imports directly or indirectly module B, and 
> module B imports directly or indirectly module A, and both of them have 
> the *same kind* of static ctor or dtor, then it errors and refuses to 
> run the program (I'm sure all of you have seen this error).
> 
> Now, if that doesn't happen, it has a list of modules, of what imports 
> whatever else. And it can call the static ctors in the order of that 
> graph making sure dependent modules are constructed first. It does this 
> separately for shared and unshared ctors/dtors. Standalone modules are 
> called first, and are not included in the search for cycles.
> 
> On program/thread termination, it calls the dtors in the opposite order.
> 
> Two things that it CANNOT detect:
> 
> 1. If you circumvent the module system to call functions in static 
> ctor/dtors using extern(C).
> 2. If you establish any dependencies during runtime, such as pushing 
> into module A's global array a reference to a module B global object, 
> without module A or B importing each other. It won't know to call module 
> A's dtor first.
> 
> I'm guessing the latter is what you are having issues with.
> 
> -Steve

Thank you for the explanation. I guess I'm dealing with case
2. But then, how is D supposed to deal with this situation?
Naturally the concepts of "external resources" and "singleton"
are orthogonal and the two modules _should_ not know about
each other.
Granted, a D singleton class is never going to be part of an
external system resource ;), but building on the idea,
whenever we have static dtors in templates, we risk that the
template arguments introduce a "hidden" dependency. The type
is `T` and Singleton.d does not import the module that `T`
came from, which would transitively import Resource.d and make
sure static dtors in there are deferred until after
Singleton.d's dtors were called.

Effectively templated module dtors are crashes waiting to be
triggered!

The compiler must add any modules as dependencies that are
passed in through template arguments as if the concrete type
was directly used with any required import.

-- 
Marco


More information about the Digitalmars-d mailing list