generic list of value types with sequential layout and pack size -> x86 JIT engine bug - by Jan Asselman

Status : 

  Duplicate<br /><br />
		This item appears to be a duplicate of another existing Connect or internal item.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


4
0
Sign in
to vote
ID 583519 Comments
Status Closed Workarounds
Type Bug Repros 4
Opened 8/5/2010 12:02:18 AM
Access Restriction Public

Description

The following code throws an ExecutionEngineException when I run the release build executable (run .exe file)



value type with pack size = 1:


[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RunLong
{
    public byte Count;
    public long Value;

    public RunLong(byte count, long value)
    {
        Count = count;
        Value = value;
    }
}



Using the struct in a generic List(T), adding values and getting or setting its value property makes the executable crash if it has been built in release mode. The crash doesn't occur when the executable is built in debug mode or when running the code inside visual studio debugger (release or debug mode).



List<RunLong> runs = new List<RunLong>(1024);

for (int i = 0; i < 1000; i++)
    runs.Add(new RunLong(1, i));

RunLong last = runs[runs.Count - 1];

last.Count = (byte)(last.Count + 1);

runs[runs.Count - 1] = last;



I am running VS 2010, .net 4, Win XP SP3





*************

original StackOverflow post:

http://stackoverflow.com/questions/3407616/generic-list-of-value-types-with-sequential-layout-and-pack-size-bug


--> Reply @ stackoverflow by Jared Parsons:

This does appear on the surface to be a bug in the x86 JIT engine. This only repros under the following circumstances

    * Compile in Retail
    * Compile for x86
    * Run without Visual Studio Debugger (repros under WinDbg though)

It does not repro in amd64 mode though which makes me suspect it's either

   1. An alignment issue (aka. bug in your code)
   2. A x86 JIT issue

I'm not an expert in alignment by any means but I believe your code to be correct. Please file a bug on connect to make sure the issue is investigated and add the bug link to the comment section of my answer (I'd like to track it internally). 

Sign in to post a comment.
Posted by MikeTyler on 5/21/2012 at 2:59 PM
Was this issue resolved? I seem to be encountering the same problem. I see that it is marked as a duplicate, but there is no reference to the "original" report.
Posted by Microsoft on 8/13/2010 at 9:11 AM
Got it repro'ing with the original. We'll get this fixed!
Posted by Jan Asselman on 8/9/2010 at 5:06 AM
So the bug has nothing to do with generics. It IS a x86 JIT compiler bug. If it set pack size to 4 or 8 or if I don't set the layout, then the sample program does NOT crash. So I believe it does have to do with the structure's memory alignment
Posted by Jan Asselman on 8/9/2010 at 5:02 AM
A simplified version to reproduce the bug (crashes from .net 2.0 up to .net 4.0):

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RunLong
{
    public byte Count;
    public long Value;

    public RunLong(byte count, long value)
    {
        Count = count;
        Value = value;
    }
}

class TestClass
    {
        int i = 0;
        RunLong[] items = new RunLong[16];

        public RunLong this[int index]
        {
            get { return items[index]; }
            set { items[index] = value; }
        }

        public void Add(RunLong item)
        {
            if (i >= items.Length)
            {
                RunLong[] items_old = items;
                items = new RunLong[items.Length * 2];
                Array.Copy(items_old, items, items_old.Length);
            }

            items[i++] = item;
        }
    }

[STAThread]
static void Main()
{
     TestClass tc = new TestClass();
     tc.Add(new RunLong(1, 5));
}
Posted by Microsoft on 8/5/2010 at 11:51 PM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Posted by Mike Danes on 8/5/2010 at 3:18 AM
Nothing to do with alignment (though reading unaligned int/longs is not a good idea). The code x86 generated by the JIT is bogus. Among the generated instructions there's this one:

00000083 mov         word ptr [esp+1],cs

which doesn't make any sense.