Расположение типа значения .NET в памяти

У меня есть следующие типы значений .NET:

[StructLayout(LayoutKind.Sequential)]
public struct Date
{
    public UInt16 V;
}

[StructLayout(LayoutKind.Sequential)]
public struct StringPair
{
    public String A;
    public String B;
    public String C;
    public Date D;
    public double V;
}

У меня есть код, который передает указатель на тип значения в неуправляемый код, а также смещения, обнаруженные путем вызова System.Runtime.InteropServices.Marshal.OffsetOf. Неуправляемый код заполняет дату и двойные значения.

Смещения, о которых сообщается для структуры StringPair, в точности соответствуют ожиданиям: 0, 8, 16, 24, 32.

У меня есть следующий код в тестовой функции:

FieldInfo[] fields = typeof(StringPair).GetFields(BindingFlags.Instance|BindingFlags.Public);

for ( int i = 0; i < fields.Length; i++ )
{
    int offset = System.Runtime.InteropServices.Marshal.OffsetOf(typeof(StringPair), fields[i].Name).ToInt32();

    Console.WriteLine(String.Format(" >> field {0} @ offset {1}", fields[i].Name, offset));
}

Который распечатывает именно эти смещения.

 >> field A @ offset 0
 >> field B @ offset 8
 >> field C @ offset 16
 >> field D @ offset 24
 >> field V @ offset 32

Затем у меня есть некоторый тестовый код: foreach (пара StringPair в парах) {Date d = pair.D; double v = пара. V; ...

Который имеет следующий ассемблер, связанный с ним в отладчике:

               Date d = pair.D;
0000035d  lea         rax,[rbp+20h] 
00000361  add         rax,20h 
00000367  mov         ax,word ptr [rax] 
0000036a  mov         word ptr [rbp+000000A8h],ax 
00000371  movzx       eax,word ptr [rbp+000000A8h] 
00000378  mov         word ptr [rbp+48h],ax 

                double v = pair.V;
0000037c  movsd       xmm0,mmword ptr [rbp+38h] 
00000381  movsd       mmword ptr [rbp+50h],xmm0 

Он загружает поле D со смещением 32 (0x20) и поле V со смещением 24 (0x38-0x20). JIT изменил порядок вокруг. Отладчик Visual Studio также показывает этот перевернутый порядок.

Почему!? Я вырывал свои волосы, пытаясь понять, где моя логика идет не так. Если я поменяю местами порядок D и V в структуре, то все будет работать, но этот код должен уметь работать с архитектурой плагинов, в которой другие разработчики определили структуру, и нельзя ожидать, что они запомнят загадочные правила компоновки.

Ответы на вопрос(3)

Ваш ответ на вопрос