Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguity in initialization order of static variables

During my research into the best way to build a Singleton in C# I stumbled across the following article where there is a brief mention that in C++

"The C++ specification left some ambiguity around the initialization order of static variables."

I ended up looking into the question and found this and this. Where basically the point (as far as I understand) is that the initialization order of static variables in C++ is undefined. Ok I guess so far so good, but then I wanted to understand the following statement that the article later makes

"Fortunately, the .NET Framework resolves this ambiguity through its handling of variable initialization."

So I found this page where they say

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration.

and give the example of

using System;
class Test
{
   static void Main() {
      Console.WriteLine("{0} {1}", B.Y, A.X);
   }
   public static int F(string s) {
      Console.WriteLine(s);
      return 1;
   }
}
class A
{
   static A() {}
   public static int X = Test.F("Init A");
}
class B
{
   static B() {}
   public static int Y = Test.F("Init B");
}

the output must be: 
Init B 
Init A
1 1

"Because the rules for when static constructors execute (as defined in Section 10.11) provide that B's static constructor (and hence B's static field initializers) must run before A's static constructor and field initializers."

But where I am confused is that my understanding was that the initialization order of static variables in these examples would be based on when a method or field within the class was first invoked, which is in turn based on the execution order of the block of code (this case left to right). IE: Completely independent of where - or the order - of the class declaration. Yet by my interpretation of that article it says its as a result of the order of declaration of those classes, which my testing doesn't back up?

Could someone please clarify this (and the point the article is trying to make) for me and perhaps provide a better example that illiterates the behaviour described?

like image 376
Maxim Gershkovich Avatar asked Jul 09 '12 09:07

Maxim Gershkovich


People also ask

What is the order of static variable initialization across one program?

Within a single compilation unit, static variables are initialized in the same order as they are defined in the source (this is called Ordered Dynamic Initialization). Across compilation units, however, the order is undefined: you don't know if a static variable defined in a.

What is static initialization order fiasco?

The static initialization order fiasco refers to the ambiguity in the order that objects with static storage duration in different translation units are initialized in.

Are static variables initialized first?

Static variables are initialized only once , at the start of the execution. These variables will be initialized first, before the initialization of any instance variables. A single copy to be shared by all instances of the class. A static variable can be accessed directly by the class name and doesn't need any object.

How are static variables initialized?

A static variable in a block is initialized only one time, prior to program execution, whereas an auto variable that has an initializer is initialized every time it comes into existence. A static object of class type will use the default constructor if you do not initialize it.


1 Answers

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration.

This means that within the same class, static fields are initialized in order of appearance in the source code. For example:

class A
{
   public static int X = Test.F("Init A.X");
   public static int Y = Test.F("Init A.Y");
}

When it's time for the static fields to be initialized, X is guaranteed to be initialized before Y.

"Because the rules for when static constructors execute (as defined in Section 10.11) provide that B's static constructor (and hence B's static field initializers) must run before A's static constructor and field initializers."

This means that the static constructor and member initialization for each class will run in evaluation order when expressions that access these classes appear¹. The relative order of appearance of the class definitions in source code does not play any role, even if they appear in the same source file (which they most certainly are not obliged to do). For example:

static void Main() {
    Console.WriteLine("{0} {1}", B.Y, A.X);
}

Assuming that neither A nor B has already been statically initialized, order of evaluation guarantees that all the fields of B will be initialized before any field of A. The fields of each class will be initialized in the order specified by the first rule.


¹ for the purposes of this discussion I am ignoring the existence of beforefieldinit.

like image 161
Jon Avatar answered Oct 10 '22 18:10

Jon