ToB企服应用市场:ToB评测及商务社交产业平台

标题: 探究C#中Class和Struct互相嵌套的内存问题 [打印本页]

作者: 西河刘卡车医    时间: 2023-6-10 21:04
标题: 探究C#中Class和Struct互相嵌套的内存问题
内存分区

先回顾一下C#的内存种类
内存分配

值类型分配在栈上,引用类型分配在堆上,这个概念一般都是比较清楚的。但是遇到下面的情况内存又是如何分配的呢?
Struct中嵌套Class对象
  1. using System.Runtime.InteropServices;
  2. namespace MyNamespace
  3. {
  4.     namespace MyNamespace
  5. {
  6.     public class B
  7.     {
  8.         public int x;
  9.         public byte y;
  10.     }
  11.     public struct A
  12.     {
  13.         public byte x;
  14.         public B b;
  15.     }
  16.     public class Test
  17.     {
  18.         static A a;
  19.         public static void Main()
  20.         {
  21.             a = new A()
  22.             {
  23.                 x = 1,
  24.                 b = new B() { x = 1, y = 1 },
  25.             };
  26.             System.Console.WriteLine(Marshal.SizeOf(a));
  27.         }
  28.     }
  29. }
复制代码
思考一下打印出来的值会是多少?
32位系统:

64位:

原因:
结论:Struct中嵌套Class引用对象,持有的是Class的引用指针。
Claas中嵌套Struct
  1. using System.Runtime.InteropServices;
  2. namespace MyNamespace
  3. {
  4.     public class B
  5.     {
  6.         public int x;
  7.         public A y;
  8.     }
  9.     public struct A
  10.     {
  11.         public int x;
  12.         public byte y;
  13.     }
  14.     public class Test
  15.     {
  16.         static B b;
  17.         public static void Main()
  18.         {
  19.             b = new B()
  20.             {
  21.                 x = 1,
  22.                 y = new A() { x = 1, y = 1 },
  23.             };
  24.         }
  25.     }
  26. }
复制代码
通过对堆内存进行快照
32位:

64位:

出乎意料的内存大小!为什么会是这样的内存大小,我们先研究一下如果仅仅只有一个空对象,这个对象在内存中的大小是多少呢?我们通过查阅.Net官方文档看一下,一个对象是如何分配的:

引用类型变量(如smallObj)以固定大小(4字节)存储在栈上,并指向在托管堆上分配的对象实例的地址。 smallObj的实例包含指向相应类型的MethodTable的TypeHandle(类型对象指针)和syncblk index(同步块索引,用来做线程同步的,这里就不详细讲了,大家可以去原文查看)。最后当一个类没有定义任何实例字段,它将产生4个字节的开销(用于分配到栈上来对他进行引用)。这样我们就可以算出32位下一个空对象的内存大小了:4(syncblk index)+ 4(TypeHandle)+ 4(Instance Fields)= 12个字节。同理在64位下将会是24个字节。
返回到上面的测试用例,这时候我们就明白为什么是这样的内存分配大小了。32位下:基础的12个字节 + 4字节(int)+ 4字节(Struct指针) = 20个字节。64位下的32个字节留给大家思考是怎么样一个组成的呢?
总结



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4