views:

2960

answers:

8

Can I control the order static objects are being destructed? Is there any way to enforce my desired order? For example to specify in some way that I would like a certain object to be destroyed last, or at least after another static onject?

Cheers, Gal

A: 

No, you can't. You should never rely on the other of construction/destruction of static objects.

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

Martin Cote
+16  A: 

The static objects are destructed in the reverse order of construction. And the order of construction is very hard to control. The only thing you can be sure of is that two objects defined in the same compilation unit will be constructed in the order of definition. Anything else is more or less random.

Arkadiy
There are techniques to work around the problem if you need an order: see http://stackoverflow.com/questions/335369/finding-c-static-initialization-order-problems#335746
Martin York
+3  A: 

Short answer: In general, no.

Slightly longer answer: For global static objects in a single translation-unit the initialization order is top to bottom, the destruction order is exactly reverse. The order between several translation-units is undefined.

If you really need a specific order, you need to make this up yourself.

gimpf
Although your order I normally right I think the standard doesn't require order so it's really compiler dependant.
Robert Gould
Sorry, I could not understand this comment.Yes, the order is between translation units is random. Did I say something else?
gimpf
Dude! Was I ever sleepy when I wrote that! Even I have no idea what I meant :)
Robert Gould
A: 

As others have noted, it is extremely difficult to control both construction and destruction order of static objects. Instead, prefer a Close() method or similar construct which can be called in an orderly fashion.

Ryan
+2  A: 

Static objects are destroyed in the reverse of the order in which they're constructed (e.g. the first-constructed object is destroyed last), and you can control the sequence in which static objects are constructed, by using the technique described in Item 47, "Ensure that global objects are initialized before they're used" in Meyers' book Effective C++.

For example to specify in some way that I would like a certain object to be destroyed last, or at least after another static onject?

Ensure that it's constructed before the other static object.

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

I'll ignore (for simplicity) the fact that they're not in the same DLL.

My paraphrase of Meyers' item 47 (which is 4 pages long) is as follows. Assuming that you global is defined in a header file like this ...

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

... add some code to that include file like this ...

//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 which includes GlobalA.h (for example, your GlobalB.cpp source file which defines your second global variable) will define a static instance of the InitA class, which will be constructed before anything else in that source file (e.g. before your second global variable).

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

ChrisW
How can I control the construction order? not all of the statics are in the same dll.
Gal Goldman
Edited to answer your question
ChrisW
+2  A: 

The other answers to this insist that it can't be done. And they're right, according to the spec -- but there is a trick that will let you do it.

Create only a single static variable, of a class or struct that contains all the other things you would normally make static variables, like so:

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

    Var1Type *pvar1;
    Var2Type *pvar2;
};

static StaticVariables svars;

You can create the variables in whatever order you need to, and more importantly, destroy them in whatever order you need to, in the constructor and destructor for StaticVariables. To make this completely transparent, you can create static references to the variables too, like so:

static Var1Type &var1(*svars.var1);

Voilà -- total control. :-) That said, this is extra work, and generally unnecessary. But when it is necessary, it's very useful to know about it.

Head Geek
A: 

Theres no way to do it in standard C++ but if you have a good working knowledge of your specific compiler internals it can probably be achieved.

In Visual C++ the pointers to the static init functions are located in the .CRT$XI segment (for C type static init) or .CRT$XC segment (for C++ type static init) The linker collects all declarations and merges them alphabetically. You can control the order in which static initialization occurs by declaring your objects in the proper segment using

#pragma init_seg

for example, if you want file A's objects to be created before file B's:

File A.cpp:

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

File B.cpp:

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

.CRT$XCB gets merged in before .CRT$XCC. When the CRT iterates through the static init function pointers it will encounter file A before file B.

In Watcom the segment is XI and variations on #pragma initialize can control construction:

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

...see documentation for more

David Mott