Układ typu wartości .NET w pamięci
Mam następujące typy wartości .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;
}
Mam kod, który przekazuje wskaźnik do typu wartości do kodu niezarządzanego, wraz z przesunięciami wykrytymi przez wywołanie System.Runtime.InteropServices.Marshal.OffsetOf. Kod niezarządzany zapełnia datę i podwójne wartości.
Przesunięcia zgłaszane dla struktury StringPair są dokładnie tym, czego oczekiwałbym: 0, 8, 16, 24, 32
W funkcji testowej mam następujący kod:
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));
}
Który drukuje dokładnie te przesunięcia.
>> field A @ offset 0
>> field B @ offset 8
>> field C @ offset 16
>> field D @ offset 24
>> field V @ offset 32
Następnie mam jakiś kod testowy: foreach (para StringPair w parach) {Data d = pair.D; double v = pair.V; ...
Z którym debuggerem powiązany jest następujący asembler:
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
Ładuje pole D przy przesunięciu 32 (0x20) i polu V przy przesunięciu 24 (0x38-0x20). JIT zmienił porządek. Debuger Visual Studio pokazuje również tę odwróconą kolejność.
Czemu!? Wyciągam włosy, próbując zobaczyć, gdzie moja logika się nie udaje. Jeśli zamieniam kolejność D i V w strukturze, to wszystko działa, ale ten kod musi być w stanie poradzić sobie z architekturą wtyczek, w której inni programiści zdefiniowali strukturę i nie można oczekiwać, że zapamiętają tajemne reguły układu.