在内存中的.NET值类型的布局 [英] Layout of .NET value type in memory
问题描述
我有以下.NET值类型:
I have the following .NET value types:
[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;
}
我有code,它是传递一个指针的值类型非托管code,同时通过调用System.Runtime.InteropServices.Marshal.OffsetOf发现偏移。非托管code为填充日期和双重价值。
I have code that is passing a pointer to a value type to unmanaged code, along with offsets discovered by calling System.Runtime.InteropServices.Marshal.OffsetOf. The unmanaged code is populating the Date and double values.
这是报告的StringPair结构的偏移量是正是我所期望的:0,8,16,24,32
The offsets that are reported for the StringPair struct are exactly what I would expect: 0, 8, 16, 24, 32
我有以下的code的测试功能:
I have the following code in a test function:
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));
}
打印出究竟这些偏移。
Which prints out exactly these offsets.
>> field A @ offset 0
>> field B @ offset 8
>> field C @ offset 16
>> field D @ offset 24
>> field V @ offset 32
我则有一些测试code: 的foreach(StringPair对成对) { 日期D = pair.D; 双V = pair.V; ......
I then have some test code: foreach (StringPair pair in pairs) { Date d = pair.D; double v = pair.V; ...
这与它在调试器相关的汇编程序如下:
Which has the following assembler associated with it in the debugger:
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调试器显示了这个顺序颠倒了。
It is loading the D field at offset 32 (0x20) and the V field at offset 24 (0x38-0x20). The JIT has changed the order around. The Visual Studio debugger shows this inverted order too.
为什么!?我一直在拉我的头发尽量看到我的逻辑是怎么了。如果我换D和第五的秩序结构,然后一切正常,但这code需要能够应对在其他开发人员定义的结构一个插件架构,他们不能指望记得奥术布局规则。
Why!? I've been pulling my hair out try to see where my logic is going wrong. If I swap the order of D and V in the struct then everything works, but this code needs to be able to deal with a plugin architecture where other developers have defined the struct, and they can't be expected to remember arcane layout rules.
推荐答案
您在Marshal类中得到的信息是只有在类型实际上被封有关。一个管理结构的内存布局是不是发现通过任何记录手段,除了偷看大会code可能。
The info you get from the Marshal class is only relevant if the type actually gets marshaled. The internal memory layout of a managed structure is not discoverable through any documented means, other than peeking at the assembly code perhaps.
这意味着在CLR是自由重组结构的布局,优化填料。交换为D和V领域作出应有的两倍对齐要求你的结构更小。它可以节省您的64位机上6个字节。
Which means the CLR is free to reorganize the layout of the structure and optimize the packing. Swapping the D and V fields makes your structure smaller due the alignment requirements of a double. It saves 6 bytes on your 64-bit machine.
不知道为什么,这将是你的问题,它不应该是。考虑Marshal.StructureToPtr()来获取结构布置的,你想要的方式。
Not sure why this would be an issue for you, it shouldn't be. Consider Marshal.StructureToPtr() to get the structure laid-out the way you want it.
这篇关于在内存中的.NET值类型的布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!