简体   繁体   中英

Static initialization of variables fails

I stumbled across a problem from nowhere.

Suddenly my project that I am working on stopped working. I'm using Xcode 5.1.1 (LLVM 3.4, clang 5.1). The issue is that most static variables doesn't get initialized anymore at startup.

I didn't change anything which could lead to this problem but I'm curious to know what could have caused it and possibly how to solve it.

I'm talking about simple situations like:

// File.h 
class MyClass {
  static std::vector<MyObject*> data;
}

// File.cpp
std::vector<MyObject*> MyClass::data;

By running the program I get a length exception when trying to add elements to the vector, to realize that its size is just a garbage value. This happened to other static fields in other files with no apparent reason. The code itself is not used as a library but compiled as it is, and it worked flawlessly so far.

EDIT: building the release scheme doesn't show the problem, just to add more unpredictability.

EDIT: Things are even weirder than I expected. Another static variables which I manually initialized doesn't work too. The offending code is the following:

// .h
class MyClass {
  static MyClass* i;
public:
  static void init();
  static MyClass* getInstance();
}

// .cpp
MyClass* MyClass::i;

void MyClass::init() { i = new MyClass(); }
MyClass* getInstance() { return i; }

Now if I watch the values of i after the init() is called and when getInstance() is used for the first time I get two different addresses:

(lldb) p MyClass::i
(MyClass *) $0 = 0x09e36a50

(lldb) p MyClass::i
(MyClass *) $1 = 0x00620000

And I don't get how this is possible since ( init() ) is called just once (and before (getInstance()`)

When you declare statically-scoped objects in different translation units, their relative order of construction is unspecified.

If, for example, you're trying to use MyClass::Data from code that runs as part of a constructor for some other statically-scoped object, in some other translation unit, it's not specified whether or not MyClass::Data is going to get constructed before or after the other statically-scoped object's constructor. If that code that accesses MyClass::Data gets invoked, and MyClass::Data is not constructed yet, that's obviously undefined behavior.

In most common C++ implementations, the order of construction depends upon what the linker does to piece together the final executable; and it is perfectly possible that various changes to your overall application now resulted in the linker stiching together the different object modules in a different order, and changing the relative construction order of statically-scoped objects.

Many implementations provide implementation-specific mechanisms to control the construction/initialization order of statically-scoped objects. gcc, for example, has an init_priority attribute that can be used to control this, see https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM