Bug 601 - Static initialization not done
Summary: Static initialization not done
Status: RESOLVED INVALID
Alias: None
Product: Runtime
Classification: Mono
Component: JIT ()
Version: unspecified
Hardware: Macintosh Mac OS
: --- blocker
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-09-02 06:32 UTC by Jonathan Shore
Modified: 2011-09-27 15:21 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
The class with the static initialization problem (12.45 KB, application/octet-stream)
2011-09-02 06:32 UTC, Jonathan Shore
Details
The main function and ctor invocation that produces the problem (219 bytes, application/octet-stream)
2011-09-02 06:33 UTC, Jonathan Shore
Details
The exe with null reference exception due to static init order (8.00 KB, application/x-msdownload)
2011-09-05 08:51 UTC, Jonathan Shore
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED INVALID

Description Jonathan Shore 2011-09-02 06:32:19 UTC
Created attachment 240 [details]
The class with the static initialization problem

Description of Problem:

Within a constructor a call to a static function is made.  This static function refers to a static readonly array (int[]).  The compiler, however, has failed to order the initialization of static fields relative to static function calls correctly, such that the variable reference comes back with an uninitialized value (null).

My understanding from the C# spec is that the static fields, though initialized in lexical order, should all be initialized prior to the first usage by a method.

I wrote some simple test cases that appeared to work correctly.  However, in this more complicated struct (you can change to class and get the same behavior), the initialization failed.

I will include the class and the main.

Note that I am using 2.10.5 under MonoDevelop 2.6 rc1.  This was compiled and debugged within that context.

Steps to reproduce the problem:
1. Run the test
2. Observe that a Null pointer exception is thrown


Actual Results:

Null pointer exception

Expected Results:

Initialized static fields and no exception

How often does this happen? 

Always

Additional Information:
Comment 1 Jonathan Shore 2011-09-02 06:33:15 UTC
Created attachment 241 [details]
The main function and ctor invocation that produces the problem
Comment 2 Marek Safar 2011-09-02 06:44:29 UTC
-> runtime

I cannot reproduce it on linux with master or 2.6
Comment 3 Jonathan Shore 2011-09-02 06:59:16 UTC
Is there a newer released version than 2.10.5 for the mac?  Running off of a compilation off of the head would be a bit risky.

If indeed the static initialization is JIT / runtime, I also ran the exe on my linux VM with 2.6.7 and encountered the same behavior. 

If it is the compiler, I will try compiling with the MS compiler and see whether the exe generated behaves differently on these machines / runtimes.   Will report results ...
Comment 4 Jonathan Shore 2011-09-02 07:18:24 UTC
I tested with the .NET compiler and it actually exhibited the same behavior (i.e., the MonthLengths field was not initialized, in spite of being used by a static function).   To adjust so that worked moved MonthLengths to the top of the class.

However, I do not believe that should be required given the following statement on msdn:

http://msdn.microsoft.com/en-us/library/aa645758(v=vs.71).aspx
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. If a static constructor (Section 10.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. 

"prior to the first use of a static field of that class".  I am not sure what "first use" means, but thought would imply first use by a ctor or other method.

What is the correct interpretation.   Do I need to move all of my statics to the top of the class (whereas I prefer to put all private fields at the bottom, to allow a viewer to focus on the public members and contract.

I think the reason that this is not initialized is that the first construction occurs while initializing another static field that occurs before the dependent.

If this is correct behavior, I guess I'll just adjust my ordering.
Comment 5 Zoltan Varga 2011-09-03 21:25:23 UTC
I can't reproduce this either. Please attach the failing .exe file.
Comment 6 Jonathan Shore 2011-09-05 08:51:30 UTC
Created attachment 252 [details]
The exe with null reference exception due to static init order

The initialization failure may be correct relative to the .NET spec, I am not sure.   It is not ideal behavior (as would be something handled in java), but the spec is what it is.

Find the exe enclosed.   Feel free to close this bug if you think the initialization behavior is correct OR works in later .NET runtimes.
Comment 7 Zoltan Varga 2011-09-05 09:11:57 UTC
This is not a mono bug. As the spec says:

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 is executed first:

		public static readonly FDate	MAXDATE		= new FDate (9000,1,1);

then this:

		readonly static int[]		MonthLengths	= new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

but the FDate .ctor refers to the MonthLengths field, which is not yet initialized.
Comment 8 Zoltan Varga 2011-09-27 15:21:40 UTC
-> NOTABUG.