Edit: spelling
Edit: spelling
Basically I only let children of one class be statically initialized (and enforced this with a tool that goes through the generated binary and type information). These 'subsystem' classes then gets callbacks after all of the static initializers have run which allows them to find the other subsystems they depend on, and then that dependency graph is walked to initialize the full system (the dependency graph has to be a DAG or the system faults). Combined with a code review rule that static initializations only happen in one compilation unit in an anonymous namespace, and nothing else can happen there, means that no one can really touch other subsystems before they've all been initialized, and therefore the order doesn't matter.
I was really happy with how it turned out, despite being completely off the wall compared to how C++ normally works.
embedded systems software in one phrase. :-D
This is such a notorious problem, it even has a name: Static Initialisation Order Fiasco (see: https://isocpp.org/wiki/faq/ctors#static-init-order)
The symmetrical Static Destruction Order Fiasco is also a very fun problem to deal with. The solution proposed for SIOF in the C++ FAQ does nothing to help you deal with this one, though.
Deviating with a war story now, I once modified some startup code so it self-detected its boot location and initialized the ram data according to this location shift. It was fun, but debugging code you relocated is a pain because you need to somehow relocate the symbols as well.
I also wanted to maintain full functionality even at shifted location in case the self-copy process somehow failed. Never did fail, at least to my knowledge.
Is atexit the post-main hook to which you were referring, or is that just the posix hook into a larger class of post-main hooks?