存储C#

时间:2015-11-06 08:13:08

标签: c# memory-management

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

  

在静态类中,Singleton对象存储在堆上   存储在堆栈中。

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

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

How is memory allocated for a static variable?

它被描述为

  

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

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

5 个答案:

答案 0 :(得分:9)

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

类不存储在内存中。加载类时,可以将其元数据加载到内存中并进行缓存。除了那些类没有存储在内存中。

问自己,如果静态类存储在堆栈中,你怎么能在所有线程中访问它?

静态变量

  

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

参考this article for more info

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

答案 1 :(得分:3)

斯里兰姆·萨基蒂尔解释说。基本上堆内存分为两个主要部分。对象堆内存和Loader堆内存。根据我的理解,所有非静态引用类型都存储在对象堆上,所有静态对象(可能是引用类型或值类型)都存储在loader heap中。 Gc从不在加载器堆上工作,这就是为什么它们只启动一次并通过应用程序保留在内存中。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

  • 堆栈参考:对本地对象的引用。这样的根在方法执行期间存在。
  • 静态参考:对静态对象的引用。这些根源贯穿整个应用领域的生命周期。
  • 句柄:通常,这些是用于托管代码和非托管代码之间通信的引用。这样的根必须至少存在,直到非托管代码需要"托管"对象。
  • Finalizer参考:对等待完成的对象的引用。这些根源一直存在,直到终结者运行。

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

高频堆

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

Static Data and Constants Are Stored on the Heap enter image description here

enter image description here

enter image description here enter image description here

答案 4 :(得分:-1)

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