Home > Mobile >  Is static initialization order fiasco Undefined or Implementation-defined behavior?
Is static initialization order fiasco Undefined or Implementation-defined behavior?

Time:08-08

In "Programming principles and practice using C " by Stroustrup, it is recommended not using a lot of global objects especially those that depend on each other:

8.6.2 Global initialization

Global variables (and namespace variables; see §8.7) in a single translation unit are initialized in the order in which they appear. For example:

// file f1.cpp
int x1 = 1;
int y1 = x1 2;
// y1 becomes 3

This initialization logically takes place "before the code in main() is executed."

Using a global variable in anything but the most limited circumstances is usually not a good idea. We have mentioned the problem of the programmer having no really effective way of knowing which parts of a large program read and/or write a global variable (§8.4). Another problem is that the order of initialization of global variables in different translation units is not defined. For example:

// file f2.cpp
extern int y1;
int y2 = y1 2;
// y2 becomes 2 or 5

Such code is to be avoided for several reasons: it uses global variables, it gives the global variables short names, and it uses complicated initialization of the global variables. If the globals in file f1.cpp are initialized before the globals in f2.cpp , y2 will be initialized to 5 (as a programmer might naively and reasonably expect).

However, if the globals in file f2.cpp are initialized before the globals in f1.cpp , y2 will be initialized to 2 (because the memory used for global variables is initialized to 0 before complicated initialization is attempted). Avoid such code, and be very suspicious when you see global variables with nontrivial initializers; consider any initializer that isn’t a constant expression complicated.

  • I think the problem in this example is called "Static Initialization Order Fiasco":

  • So if globals in f2.cpp are initialized before those in f1.cpp then y2 has the value 2: does this mean this Undefined Behavior? or Implementation-defined Behavior?

"y2 will be initialized to 2 (because the memory used for global variables is initialized to 0 before complicated initialization is attempted) " but that memory hasn't been set aside yet so how could it be initialized to 0? because control doesn't pass by the definition of globlas in file1.cpp yet. So I think it is UB.

  • If I manually compile those files starting with file1.cpp then file2.cpp then I link and run the program; Does the same problem of initialization persist? e.g:

     g   -c file1.cpp 
     g   -c file2.cpp
     g   -c main.cpp
    

Then:

 g   file1.o file2.o main.o -o prog
 ./prog

CodePudding user response:

It's neither.

When there is a finite set of possible outcomes, and the Standard does not require the implementation to document what happens, the result is known as Unspecified Behaior. In this case, "y2 becomes 2 or 5" clearly has two possible outcomes, and formatting your hard disk isn't on the list.

As for zero-initialization: remember that the Standard does not prescribe how an implementation achieves the required effect. Globals will be, or appear to be, initialized to 0. But remember that C is a compiled language. The compiler has seen your entire program before the program is started. It knows exactly which globals exist, and how big they are.

CodePudding user response:

Is static initialization order fiasco Undefined or Implementation-defined behavior?

It's implementation defined but can also be both. It may depend on the build system used and the order you're linking your compiled translation units together.

  • If your implementation does not clearly state what happens when you deals it this hand - the behavior is undefined.

An implementation isn't always capable of sorting this out if you compile each translation unit separately (or even if you do compile them together).

The solution is to never supply your compiler/linker with this situation to sort out. Always make sure that there is no possible static initialization failure possible.

  • Related