Static member variable not being initialized in Release - Compiler/clr bug?
Expected output & output I get in debug mode, and release mode under VS2010, .NET 4.0:
bar construct
main
Output in release mode not under the VS2010 debugger, and under WinDbg:
main
Program does not exhibit this behavior on VS2005, .NET 2.0
using System;
namespace static_init
{
public class bar
{
public bar()
{
Console.WriteLine("bar construct");
}
}
class Program
{
public static bar blah = new bar();
static void Main(string[] args)
{
Console.WriteLine("main");
Console.ReadLine();
}
}
}
Probably related: Static constructor can run after the non-static constructor. Is this a compiler bug?
Update
In my actual code constructor bar()
initializes some interop code with C++ (unmanaged). It needs to happen before anything else in this library - is there any way to ensure that without putting in an init()
function that touches all of the statics (with side effects that aren't externally refere开发者_开发知识库nced) in the library?
Note for future searchers: I'm using SWIG, and this is an assumption that they made in their wrapper generation code. SWIGStringHelper
is the current offender, there may be more though.
Conclusion
Update to version 2.0 of SWIG, it puts in the static constructor as needed by newer version of .NET.
It's probably getting optimized out because you don't use it.
It also isn't a compiler bug, it's in the language spec.
17.4.5.1 Static field initialization
The static field variable initializers of a class declaration correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (§17.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class
Since you never use a static field of the Program class, the static initializer isn't guaranteed to run (though it could...the 'implementation-dependent time' above)
Update
You can accomplish what you want by making Program have a static constructor.
static Program (){}
or possibly by accessing another (possibly dummy) static variable
Note that there have been some changes in .NET 4.0 regarding static initialization. Jon Skeet has written a blog post with some samples:
Type initialization changes in .NET 4.0
If you want precise initialization, you should use a static constructor (which may be empty).
using System;
namespace static_init
{
public class bar
{
public bar()
{
Console.WriteLine("bar construct");
}
}
class Program
{
public static bar blah = new bar();
// This static constructor will make sure that the type Program
// is initialized before it is first used.
//
static Program()
{ }
static void Main(string[] args)
{
Console.WriteLine("main");
Console.ReadLine();
}
}
}
精彩评论