The order of destruction of static objects in C ++

Can I control the order of static objects that are being destroyed? Is there a way to enforce my desired order? For example, to somehow indicate that I would like some object to be destroyed last, or at least after another static object?

+45
c ++ static
Jan 22 '09 at 15:32
source share
9 answers

Static objects are destroyed in the reverse order. And the construction order is very difficult to control. The only thing you can be sure of is that the two objects defined in the same compilation unit will be built in the order of definition. Everything is more or less random.

+47
Jan 22 '09 at 15:35
source share

Other answers to this insist that this is not possible. And they are right, according to the specification, but there is a trick that will allow you to do this.

Create only one static variable, class or structure that contains all the other things that you usually do static variables, for example:

class StaticVariables { public: StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { }; ~StaticVariables(); Var1Type *pvar1; Var2Type *pvar2; }; static StaticVariables svars; 

You can create variables in any order and, more importantly, destroy them in any order that you need, in the constructor and destructor for StaticVariables . To make this completely transparent, you can also create static variable references:

 static Var1Type &var1(*svars.var1); 

Voilà - full control. :-) This suggests that this is additional work and is not needed at all. But when necessary, it is very useful to know about it.

+18
Jan 22 '09 at 19:49
source share

Short answer: In general, no.

A slightly longer answer: for global static objects in one translation unit, the order of initialization is from top to bottom, the order of destruction is exactly the opposite. The order between multiple translation units is undefined.

If you really need a specific order, you need to do it yourself.

+11
Jan 22 '09 at 15:36
source share

Static objects are destroyed in the reverse order in which they are constructed (for example, the first constructed object is destroyed last), and you can control the sequence in which static objects are created using the method described in Section 47, “ Make sure that global objects are initialized before they are use "in Meyers' book Effective C ++."

For example, to somehow indicate that I would like some object to be destroyed last, or at least after another static onject?

Make sure it is created in front of another static object.

How can I control the construction order? not all statics are in the same dll.

I will ignore (for simplicity) the fact that they are not in the same DLL.

My paraphrase from paragraph 47 of Meyers (4 pages long) is as follows. Assuming you are globally defined in a header file like this ...

 //GlobalA.h extern GlobalA globalA; //declare a global 

... add code that includes such a file ...

 //GlobalA.h extern GlobalA globalA; //declare a global class InitA { static int refCount; public: InitA(); ~InitA(); }; static InitA initA; 

The effect of this will be that any file that includes GlobalA.h (for example, your original GlobalB.cpp file that defines your second global variable) will define a static instance of the InitA class that will be created before everything else in that source file (for example, before your second global variable).

This InitA class has a static reference count. When the first InitA instance is constructed, which is now guaranteed to be created before the GlobalB instance is created, the InitA constructor can do whatever it needs to do to ensure that the globalA instance is initialized.

+11
Jan 22 '09 at 15:46
source share

It is not possible to do this in standard C ++, but if you have a good knowledge of your specific internal compiler components, perhaps this is possible.

In Visual C ++, pointers to static initialization functions are located in the .CRT$XI segment (for static init type C) or the .CRT$XC segment (for C ++ type static init). The compiler collects all the ads and combines them in alphabetical order. You can control the order in which static initialization occurs by declaring your objects in the appropriate segment using

 #pragma init_seg 

for example, if you want to create objects A before file B:

A.cpp file:

 #pragma init_seg(".CRT$XCB") class A{}A; 

B.cpp file:

 #pragma init_seg(".CRT$XCC") class B{}B; 

.CRT$XCB merges before .CRT$XCC . When the CRT iterates using static pointers to the initialization function, it will encounter file A before file B.

Watcom has an XI segment, and #pragma initialize variants can control the design:

 #pragma initialize before library #pragma initialize after library #pragma initialize before user 

... see documentation for more

+4
May 05 '10 at 12:42 a.m.
source share

To read:
Initializing SO>

SO Solution for the initialization problem

+3
Jan 22 '09 at 20:31
source share

No, you can’t. You should never rely on another from constructing / destroying static objects.

You can always use singleton to control the construction / destruction of your global resources.

0
Jan 22 '09 at 15:35
source share

Do you really need a variable that needs to be initialized to main ?

If you do not, you can use a simple idiom to easily manage the order of construction and destruction, see here:

 #include <cassert> class single { static single* instance; public: static single& get_instance() { assert(instance != 0); return *instance; } single() // : normal constructor here { assert(instance == 0); instance = this; } ~single() { // normal destructor here instance = 0; } }; single* single::instance = 0; int real_main(int argc, char** argv) { //real program here... //everywhere you need single::get_instance(); return 0; } int main(int argc, char** argv) { single a; // other classes made with the same pattern // since they are auto variables the order of construction // and destruction is well defined. return real_main(argc, argv); } 

This does not stop you from actually trying to create a second instance of the class, but if you make this statement, it will fail. In my experience, it works great.

0
Feb 18 '15 at 10:41
source share

You can effectively achieve similar functionality by having static std::optional<T> instead of T Just initialize it in the same way as with a variable, use it with indirect movement and destroy it by assigning std::nullopt (or, for boost, boost::none ).

It differs from a pointer to the fact that it has pre-allocated memory, and I think you want it. Therefore, if you destroy it and, possibly, much later, recreate it, your object will have the same address (which you can save), and you do not pay for dynamic allocation / release at this time.

Use boost::optional<T> if you don't have std:: / std::experimental:: .

0
Nov 25 '16 at 19:45
source share



All Articles