Bug 16430 - Struct is not initialized with null values
Summary: Struct is not initialized with null values
Status: RESOLVED FIXED
Alias: None
Product: Compilers
Classification: Mono
Component: C# ()
Version: 3.2.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: ---
Assignee: Marek Safar
URL:
Depends on:
Blocks:
 
Reported: 2013-11-24 22:40 UTC by evolvedmicrobe
Modified: 2013-11-27 08:13 UTC (History)
4 users (show)

Tags: Runtime, Struct, Memory
Is this bug a regression?: ---
Last known good build:


Attachments
Solution File Which Recreates The Bug (7.46 MB, application/zip)
2013-11-25 12:05 UTC, evolvedmicrobe
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 FIXED

Description evolvedmicrobe 2013-11-24 22:40:07 UTC
I have a program that works in the MS runtime but not the mono runtime.  Tracking down the issue showed that mono is not clearing memory when a new structure is initialized, while the MS runtime is.  Specifically I have the following structure.


 public struct MultiWaySuffixEdge
    {
        
        public long StartIndex;
        public MultiWaySuffixEdge[] Children;
        public MultiWaySuffixEdge[] SuffixLink;
        public MultiWaySuffixEdge(long startIndex)
            : this()
        {
            this.StartIndex = startIndex;
        } 

       
    }

I expect when I create a new version of this structure it should have a null array for the Children and SuffixLink.  However, this is not the case.  The following bit of code:

      MultiWaySuffixEdge newEdge;
      newEdge = new MultiWaySuffixEdge(startIndex);

Creates a "newEdge" variable where the Children and SuffixLink values already have values (pre-filled arrays) and are not null as expected.  The arrays are filled to the last value that was used the previous time newEdge was assigned (this happens inside a loop, but presumably the "new" keyword and local scoping of the variable should clear the memory of the struct).
Comment 1 evolvedmicrobe 2013-11-24 22:49:26 UTC
I have also confirmed this issue by changing the constructor to set the arrays to null, and now the program produces the same results as the microsoft version.
Comment 2 Zoltan Varga 2013-11-25 06:44:36 UTC
Please attach some kind of reproducible testcase.
Comment 3 evolvedmicrobe 2013-11-25 12:05:59 UTC
Created attachment 5530 [details]
Solution File Which Recreates The Bug

This is a solution that recreates the bug.  Inside the directory StructFailing there is a .sln file, if opened and run, the debugger should break where I throw an exception indicating the improper behavior, that is a struct that is initialized with object references that are not null.

The solution has two items, a quick two line program that generates the bug, and  another project that represents the large library the bug was found in.  It should be very easy to verify with this, but let me know if any problems arise
Comment 4 evolvedmicrobe 2013-11-25 12:06:42 UTC
Just added a test case, please let me know if it isn't clear.
Comment 5 evolvedmicrobe 2013-11-25 12:10:03 UTC
I should also add that I found this bug on both mac OSX and CentOS 

The CentOS version of Mono I was using was 3.0.3 and the version on mac was mono 3.2.5
Comment 6 Zoltan Varga 2013-11-25 12:51:31 UTC
This is an mcs bug, when a struct ctor calls its base ctor using this (), the definite assignment test for its fields is not done.
Testcase:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<using System;
using System.Runtime.CompilerServices;

struct AStruct {

	public object foo;

	public AStruct (int i) : this () {
	}
}

public class Tests
{
	public static int Main () {
		for (int i = 0; i < 100; ++i) {
			AStruct a;

			a = new AStruct (5);
			Console.WriteLine (a.foo);
			a.foo = "A";
		}

		return 0;
	}
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

This should fail to compile with:
error CS0171: Field `AStruct.foo' must be fully assigned before control leaves the constructor
but it succeeds, and the 'foo' field is never initialized to null.
Comment 7 evolvedmicrobe 2013-11-25 15:03:10 UTC
Oh interesting.  So does this mean this is a Microsoft bug as well that it compiles?

Alternatively, should the this() constructor automatically zero out the fields?
(e.g. http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx).

Either way I'll leave it to the experts, and thanks for the quick response on this.
Comment 8 Marek Safar 2013-11-26 08:02:48 UTC
It should not fail when  the constructor calls this () which is the default constructor that does the initial assignment. Otherwise it would not be possible to instantiate this type without random data using "new AStruct ()"
Comment 9 Zoltan Varga 2013-11-26 11:19:18 UTC
When should the JIT initialize this data then ? mcs doesn't generate an initobj statement in this case:

IL_0007:  ldloca.s   V_1
    IL_0009:  ldc.i4.5
    IL_000a:  call       instance void AStruct::.ctor(int32)

But if I change the call to a = new AStruct (), it does generate an initobj:

    IL_0007:  ldloca.s   V_1
    IL_0009:  initobj    AStruct
Comment 10 Marek Safar 2013-11-26 11:22:02 UTC
Not calling initobj is mcs bug
Comment 11 Marek Safar 2013-11-27 03:36:50 UTC
Zoltan, fixing this in mcs crashes GC. Could you try https://gist.github.com/marek-safar/7672515 and build mono with that?
Comment 12 Zoltan Varga 2013-11-27 06:43:43 UTC
What crashes ?
Comment 13 Marek Safar 2013-11-27 08:13:53 UTC
Fixed in master