Marshal.SizeOf 和 sizeof 的区别,我就是不明白 [英] Difference between Marshal.SizeOf and sizeof, I just don't get it

查看:47
本文介绍了Marshal.SizeOf 和 sizeof 的区别,我就是不明白的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

直到现在我才认为 Marshal.SizeOf 是计算非托管堆上 blittable 结构的内存大小的正确方法(这似乎是 SO 上的共识以及网络上几乎所有其他地方的共识).

Until now I have just taken for granted that Marshal.SizeOf is the right way to compute the memory size of a blittable struct on the unmanaged heap (which seems to be the consensus here on SO and almost everywhere else on the web).

但是在阅读了一些针对 Marshal.SizeOf 的警告之后 (这篇文章在但是有一个问题......"之后)我试过了,现在我完全糊涂了:

But after having read some cautions against Marshal.SizeOf (this article after "But there's a problem...") I tried it out and now I am completely confused:

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 是非托管结构的错误大小运算符?

What's going wrong here? What memory layout does the field dereferencing operator '->' assume? Is '->' even the right operator for addressing unmanaged structs? Or is Marshal.SizeOf the wrong size operator for unmanaged structs?

我没有找到任何可以用我理解的语言解释这一点的内容.除了...结构布局是不可发现的..."和...在大多数情况下..."诸如此类的东西.

I have found nothing that explains this in a language I understand. Except for "...struct layout is undiscoverable..." and "...in most cases..." wishy-washy kind of stuff.

推荐答案

我认为您还没有回答的一个问题是您在特定情况下发生了什么:

I think the one question you still don't have answered is what's going on in your particular situation:

&ps2->x
0x02ca4370  <------
    *&ps2->x: 0xabcd 'ꯍ'
&ps2->y
0x02ca4372  <-------
    *&ps2->y: 0x1234 'ሴ'

您正在写入和读取(可能)未分配的内存.由于您所在的内存区域,它没有被检测到.

You are writing to and reading from (possibly) unallocated memory. Because of the memory area you're in, it's not detected.

这将重现预期的行为(至少在我的系统上,YMMV):

This will reproduce the expected behavior (at least on my system, YMMV):

  TestStruct* ps2 = (TestStruct*)Marshal.AllocHGlobal(marshalSize*10000);

  // hmmm, put to 16 bit numbers into only 2 allocated 
  // bytes, this must surely fail...
  for (int i = 0; i < 10000; i++)
  {
    ps2->x = (char)0xABCD;
    ps2->y = (char)0x1234;
    ps2++;
  }

这篇关于Marshal.SizeOf 和 sizeof 的区别,我就是不明白的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆