繁体   English   中英

静态类内存分配 C#

[英]Static class memory allocation where it is stored C#

我读了一篇让我对内存分配感到困惑的文章,其中指出:

单例对象存储在堆上,而静态类存储在堆栈上。

链接是: http : //www.dotnetjalps.com/2013/06/Static-vs-Singleton-in-Csharp-Difference-between-Singleton-and-Static.html

但是在一些 Stackoverflow 问题中,例如

如何为静态变量分配内存?

它被描述为

静态变量存储在堆上,无论它们是声明为引用类型还是值类型。 无论创建多少个实例,总共只有一个槽位。

所以我对静态类的堆栈或堆存储感到困惑。 如何为静态类分配内存,为什么? 如何为单例类分配内存?

.NET Framework 中有四种可能的根类型:

  • 堆栈引用:对本地对象的引用。 这样的根存在于方法执行期间。
  • 静态引用:对静态对象的引用。 这些根存在于整个应用程序域生命周期中。
  • 句柄:通常,这些是用于托管和非托管代码之间通信的引用。 这样的根必须至少存在到非托管代码需要“托管”对象为止。
  • 终结器引用:对等待终结的对象的引用。 这些根一直存在,直到终结器运行。

https://www.jetbrains.com/help/dotmemory/Analyzing_GC_Roots.html

高频堆

C# 程序中定义的静态数据和常量存储在堆上。 由于它们在应用程序的整个生命周期内都存在,因此不需要进行垃圾收集,因此存储在加载程序堆中,而不是普通的垃圾收集堆中。 具体来说,静态数据存储在高频堆上——每个 AppDomain 存在的加载器堆之一。

静态数据和常量存储在堆上在此处输入图片说明

在此处输入图片说明

在此处输入图片说明 在此处输入图片说明

类不会占用内存,但对象会。 声明“存储在堆栈中的静态类”对我来说听起来很荒谬。

类不存储在内存中。 当一个类被加载时,它们的元数据可能被加载到内存中并被缓存。 除此之外,类不存储在内存中。

问问自己,如果静态类存储在堆栈中,您如何能够在所有线程中访问它?

静态变量

静态变量是 MethodTable 数据结构的重要组成部分。 它们在方法表槽数组之后被分配为 MethodTable 的一部分。 所有原始静态类型都是内联的,而静态值对象(如结构和引用类型)通过句柄表中创建的 OBJECTREF 引用。 MethodTable中的OBJECTREF指的是AppDomain句柄表中的OBJECTREF,指的是堆创建的对象实例 创建后,句柄表中的 OBJECTREF 将使堆上的对象实例保持活动状态,直到卸载 AppDomain

请参阅这篇文章了解更多信息

请停止阅读该博文或该作者的任何博文。 这是完全荒谬的。

尼斯解释由 Sriram Sakthivel。 基本上堆内存分为两个主要部分。 对象堆内存和加载程序堆内存。 根据我的理解,所有非静态引用类型都存储在对象堆中,所有静态对象(可能是引用类型或值类型)都存储在加载程序堆中。 Gc 永远不会在加载程序堆上工作,这就是为什么它们只初始化一次并通过应用程序保留在内存中的原因。

静态变量去Heap内部的特殊原因。它被称为高频堆,所有的静态变量去内存中的高频堆 高频堆中的对象不是由 GC 垃圾收集的,因此在应用程序的整个生命周期中都可以使用静态变量。

我们需要明确地取消分配它然后我们必须将它设置为null以便 GC 可以清除它分配的内存。

实例通过 new 关键字创建并驻留在堆中,如果没有人指出它将被垃圾收集。 但在静态类静态构造函数的情况下,只调用一个来初始化所有静态成员的内存,这些静态成员将驻留在堆栈以外的全局内存位置,除非应用程序正在运行,否则静态成员将保持活动状态。它不会被垃圾收集。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM