迄今为止,我一直认为Marshal.SizeOf是计算非托管堆上可平坦化结构体的内存大小的正确方式(这似乎是SO和几乎所有其他网站上的共识)。
但在阅读了一些有关Marshal.SizeOf的注意事项之后(此文章中“但有一个问题…”之后),我尝试了一下,现在完全感到困惑:
public struct TestStruct
{
public char x;
public char y;
}
class Program
{
public static unsafe void Main(string[] args)
{
TestStruct s;
s.x = (char)0xABCD;
s.y = (char)0x1234;
// this results in size 4 (two Unicode characters)
Console.WriteLine(sizeof(TestStruct));
TestStruct* ps = &s;
// shows how the struct is seen from the managed side... okay!
Console.WriteLine((int)s.x);
Console.WriteLine((int)s.y);
// shows the same as before (meaning that -> is based on
// the same memory layout as in the managed case?)... okay!
Console.WriteLine((int)ps->x);
Console.WriteLine((int)ps->y);
// let's try the same on the unmanaged heap
int marshalSize = Marshal.SizeOf(typeof(TestStruct));
// this results in size 2 (two single byte characters)
Console.WriteLine(marshalSize);
TestStruct* ps2 = (TestStruct*)Marshal.AllocHGlobal(marshalSize);
// hmmm, put to 16 bit numbers into only 2 allocated
// bytes, this must surely fail...
ps2->x = (char)0xABCD;
ps2->y = (char)0x1234;
// huh??? same result as before, storing two 16bit values in
// only two bytes??? next will be a perpetuum mobile...
// at least I'd expect an access violation
Console.WriteLine((int)ps2->x);
Console.WriteLine((int)ps2->y);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
这里出了什么问题?字段解引用操作符'->'假定什么内存布局?'->'是否是寻址非托管结构的正确操作符?或者Marshal.SizeOf是非托管结构的错误大小操作符?
我没有找到任何用我理解的语言解释这个问题,除了“...结构布局是无法发现的...”和“...在大多数情况下...”这种含糊不清的东西。
Unsafe.SizeOf<T>()
; 如果这给您带来了困扰,我很抱歉。 - Marc Gravell