Initializing static objects across files and libraries in C++ results in STRINGY not initialized to the value of STRINGX

Technote (troubleshooting)


Problem(Abstract)

Attempts to compile your program with XL C/C++ compilers results in the static objects in the program not initialized to the right value.

Symptom

While compiling the following C++ program, you might assume that the objects from the module that is compiled first are initialized first. This assumption might lead to unexpected results.

X.h :
#include <string>
class CObjet {
  public:
     static const string STRINGX;
};


X.cpp:
#include <X.h>

using namespace std;
const string CObjet::STRINGX = "001";

Y.cpp:
#include <iostream>
#include <X.h>
const string STRINGY= CObjet::STRINGX;


int main () {
cout << "CObjet::STRINGX [" <<CObjet::STRINGX << "]" << endl;
cout << "STRINGY [" <<  STRINGY << "]" << endl;
return 0;
}



If you use the following commands to compile the files:

xlC -c -I./ X.cpp -o X.o
xlC -c -I./ Y.cpp -o Y.o
xlC -o binary X.o Y.o

You will get the following result when you run the executable file:

./binary
CObjet::STRINGX [001]
STRINGY []


From the result, you can see that STRINGY is not initialized to the value of STRINGX.

Cause

STRINGX and STRINGY are global static objects. STRINGY is dependent on the initialization of STRINGX. They are defined in different source files.

Although the C++ language definition specifies the initialization order for these objects within a file (which follows the order in which they are declared), it does not specify the initialization order for such objects across files and libraries.

So STRINGX might not be initialized before STRINGY even though module X.o is compiled first, resulting in empty string for STRINGY. Depending on the compiler and operating system buffer value at the time, STRINGY might even contain trash value to crash the program when it is run.

Resolving the problem

To solve the problem, some programmers move each non-local static object into its own function, where the object is declared static. They then have the function return a reference to its enclosed local static object and call the function in the sequence they want the objects to be initialized. This is usually a portable approach, but it involves tedious code changes.

The XL C/C++ compiler can make this easy for you. You can use the -qpriority or -qmkshrobj=priority or -Wm,-c options to specify the initialization order of the static objects that are declared in various files and libraries in your program. These options can assign the module a priority number and thus control the initialization order of objects.

The module that contains the main() function always has priority 0. The lowest number has the highest priority. In the above example, specifying -qpriority=-100 when compiling the X.o object can ensure objects in X.o are initialized before objects in Y.o.

Likewise, if you are building X.o into a shared library, you can use -qmkshrobj=-100 when building the library.

You can use the following commands to do the compilation:

xlC -c -I./ -qpriority=-100 X.cpp -o X.o
xlC -c -I./ Y.cpp -o Y.o
xlC -o binary X.o Y.o


or for building shared libraries:

xlC -c -I./ X.cpp -o X.o
xlC -c -I./ Y.cpp -o Y.o
xlC -qmkshrobj=-100 -o libX.so X.o
xlC -o binary -btrl Y.o -L. -lX

You will get the following result when you run the executable file:


./binary
CObjet::STRINGX [001]
STRINGY [001]

Related information

Initializing static objects in libraries (C++)

Rate this page:

(0 users)Average rating

Document information


More support for:

XL C/C++ for AIX
Compiler

Software version:

10.1, 11.1, 12.1

Operating system(s):

AIX

Reference #:

1615387

Modified date:

2012-11-21

Translate my page

Machine Translation

Content navigation