10

msdn

sizeof 运算符只能在不安全的代码块中使用。虽然可以使用 Marshal.SizeOf 方法,但此方法返回的值并不总是与 sizeof 返回的值相同。

Marshal.SizeOf 返回类型被编组后的大小,而 sizeof 返回由公共语言运行时分配的大小,包括任何**填充**。

我曾经读过这本书:c# via clr(第 522 页)

那 : 在此处输入图像描述

问题 :

1)这里提到的填充:

在此处输入图像描述

和书中提到的一样吗?

2)如果我有对象类型Person- 我怎么知道它在内存中的真实大小?

编辑-我为什么需要那个?

注意

他们有阅读记录的样本:

 using (var accessor = mmf.CreateViewAccessor(offset, length))
            {

                int colorSize = Marshal.SizeOf(typeof(MyColor)); //<--------HERE
                MyColor color;


                for (long i = 0; i < length; i += colorSize)
                {
                    accessor.Read(i, out color);
                    color.Brighten(10);
                    accessor.Write(i, ref color);
                }
            }
        }

如果报告的尺寸MARSHAL.sizeOF不是这样的尺寸sizeOF-我应该选择哪个?一定要准确!!

根据这个样本,他们不考虑填充,他们应该......(或不......)

4

1 回答 1

5

这可能看起来不诚实 - 但从内存映射文件的角度来看,您感兴趣的大小与内存中该对象的大小不同。它们可能被称为内存映射文件,但在 .Net 中,这并不一定意味着与本机代码中的完全相同 (不过,底层实现仍然相同——逻辑内存的一部分映射到文件的一部分,因此名称仍然正确)

sizeof返回物理内存中对象的正确大小,包括任何填充字节等。因此,如果您需要知道本机内存术语中对象的确切大小,请使用它(但这不适用于内存映射文件我稍后会解释)。

正如文档所说,Marshal.SizeOf从.Net的角度报告对象的大小,不包括两个隐藏的数据项;仅由运行时使用。

您复制的示例使用Marshal.SizeOf,因为填充值仅与内存中的物理对象相关。当对象被序列化时,只有逻辑.Net 数据被序列化。当对象再次加载回来时,这两个填充值会根据当时运行时的状态重新分配。例如,类型指针可能不同。序列化它们是没有意义的。这就像将本机指针(不是偏移量)序列化到磁盘一样 - 它指向的数据下次不太可能出现在同一个地方。

Ergo - 如果你想知道 100 个Color对象的数组在物理内存中的使用量 - 使用sizeof;如果您想知道相同数据的内存映射文件有多大,请使用Marshal.SizeOf.

于 2012-05-15T14:20:02.773 回答