4

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()`)

9
  • Do they get used during construction of other static objects?
    – user743382
    Commented Sep 23, 2014 at 15:57
  • @hvd: No, actually the exception is raised when allocating a heap object once the program already started (which adds itself to the std::vector) but this is true for the other cases I found too.
    – Jack
    Commented Sep 23, 2014 at 15:59
  • 6
    Non-trival static variables like this caused me too many headaches so I stopped using them. A static local in a function returned is safer I find.
    – Neil Kirk
    Commented Sep 23, 2014 at 16:02
  • 1
    @DavidSchwartz: the problem is that that static variable is not used by other static variables. It doesn't get initialized anymore at all. And all the static variables used so far in the code show the same behavior.
    – Jack
    Commented Sep 23, 2014 at 16:16
  • 2
    Perhaps bogus arguments to memcpy or similar, clobbering unrelated variables? Does your debugger support breaking on data changes? If so, you could set a regular breakpoint on MyClass::init, and after that finishes, break when i changes, and get a stack trace at that time.
    – user743382
    Commented Sep 23, 2014 at 17:32

1 Answer 1

1

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

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.