Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Controlling destructor order for global objects

I've got a class (A) that accesses (indirectly via a static method) a static variable (an STL container) in another class (B) in its constructor and destructor.

A objects may be global, global constants, static members of another class, stored in other classes (which may themselves have global or static instances) or basically anywhere else a c++ object can be.

If an A object is constructed before the static members in B or destructed after the static members in B, it will cause a crash at some point (usually an access violation).

Is there some way to guarantee that all instances of class A (except those that have leaked, since by definition there "lost" and so wont be destructed any way) are constructed after and destructed before B's static variable?

I've seen some solutions for making a specific variable be constructed/destructed before/after another, however not a general case of all instances of a given type so am not sure how to approach this.

like image 381
Fire Lancer Avatar asked Jan 29 '10 21:01

Fire Lancer


3 Answers

No. This is known as the static-initialization fiasco. The order that objects get constructed prior to entering main is unspecified. The only guarantee is that it happens.

What you can do is lazy-initialize. This means your objects won't be initialized until you use them. Such as:

struct A { /* some data */ };
struct B { B(void){ /* get A's data */ } };

A& get_A(void)
{
    static A instance;
    return instance;
}

B& get_B(void)
{
    static B instance;
    return instance;
}

You use get_A and get_B to get the global instances. The part where B uses A should use get_A, and your use of B should be with get_B. Note the get_B is optional in your case.

What happens when B is first created? (Either globally or in the function) The constructor will call get_A and that's where A will be created. This let's you control the order things get constructed.

Note I think I reversed your A and B.

like image 143
GManNickG Avatar answered Oct 03 '22 00:10

GManNickG


In general, no such method. There are workarounds, though. You can get an object with global scope and a slightly-less-than global lifetime by having a global pointer and initializing/destructing it in main/WinMain. Also, you place your global state to be destructed last in a ref-counted heap object.

Also, consider redesign :)

like image 20
Seva Alekseyev Avatar answered Oct 03 '22 00:10

Seva Alekseyev


The book "Modern C++ Design" covers this issue nicely.

Google Books contains scans of much of it - see section 6.5 (page 135) - link.

like image 30
stusmith Avatar answered Oct 03 '22 01:10

stusmith