Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

Static initialization dependency

Within a specific translation unit, the order of initialization of static objects is guaranteed to be the order in which the object definitions appear in that translation unit. The order of destruction is guaranteed to be the reverse of the order of initialization.

However, there is no guarantee concerning the order of initialization of static objects across translation units, and the language provides no way to specify this order. This can cause significant problems. As an example of an instant disaster (which will halt primitive operating systems and kill the process on sophisticated ones), if one file contains

//: C10:Out.cpp {O}
// First file
#include <fstream>
std::ofstream out("out.txt"); ///:~

and another file uses the out object in one of its initializers

//: C10:Oof.cpp
// Second file
//{L} Out
#include <fstream>
extern std::ofstream out;
class Oof {
public:
  Oof() { std::out << "ouch"; }
} oof;
int main() {} ///:~

the program may work, and it may not. If the programming environment builds the program so that the first file is initialized before the second file, then there will be no problem. However, if the second file is initialized before the first, the constructor for Oof relies upon the existence of out, which hasn’t been constructed yet and this causes chaos.

This problem only occurs with static object initializers that depend on each other. The statics in a translation unit are initialized before the first invocation of a function in that unit – but it could be after main( ). You can’t be sure about the order of initialization of static objects if they’re in different files.

A subtler example can be found in the ARM.[47] In one file you have at the global scope:

extern int y;
int x = y + 1;

and in a second file you have at the global scope:

extern int x;
int y = x + 1;

For all static objects, the linking-loading mechanism guarantees a static initialization to zero before the dynamic initialization specified by the programmer takes place. In the previous example, zeroing of the storage occupied by the fstream out object has no special meaning, so it is truly undefined until the constructor is called. However, with built-in types, initialization to zero does have meaning, and if the files are initialized in the order they are shown above, y begins as statically initialized to zero, so x becomes one, and y is dynamically initialized to two. However, if the files are initialized in the opposite order, x is statically initialized to zero, y is dynamically initialized to one, and x then becomes two.

Programmers must be aware of this because they can create a program with static initialization dependencies and get it working on one platform, but move it to another compiling environment where it suddenly, mysteriously, doesn’t work.

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire