所有静态成员存储在哪里



我正在努力学习C#如何管理内存。我一直停留在静态元素上,我读了很多关于这个主题的博客和文章,但我找不到一个非常满意的答案。

让我们定义一个代码块来帮助找到答案。

class myClass
{
    static string myStr = "String Data";
    static int myInt = 12;
}

在你们分享答案之前,让我分享一下我对这个主题的发现。请随意同意或不同意,并帮助我找到正确的答案。

  • 静态只是一辈子的事
  • 一个静态引用类型(myStr)将在生命周期内被堆起来
  • 一个静态值类型(myInt),将在生命周期内保存在堆栈中

让我困惑的是我在网上找到的一些关于这个问题的答案。

困惑1:

程序启动时,会将所有相关程序集加载到AppDomain中。加载程序集时,将调用所有静态构造函数,包括静态字段。他们将住在那里,卸载他们的唯一方法是卸载AppDomain。

在上面的几行中,明确提到所有静态元素都存储在AppDomain上。那么,为什么互联网上的每个人都说"静态"元素存储在堆/堆栈中呢?

困惑2:

每个静态变量都存储在堆上,无论它是在引用类型还是值类型中声明的。

如果每个静态变量都存储在堆上。那么,为什么有些人说值类型的静态变量存储在堆栈中呢?

请帮助连接我的点,以了解C#中静态变量的内存管理。非常感谢您的宝贵时间:)

首先,请注意,所有这些都是实现细节。运行时唯一能保证的是:

  • 当你要求一个静态场时,它就在那里
  • 静态构造函数在使用类型之前的某个时刻执行

基本上就是这样。其他的都是实现细节——规范不关心堆栈、堆或其他任何东西。这取决于运行时的实现,如果需要,一个有效的运行时可以将所有内容都放在堆栈上或堆上。别忘了寄存器。

现在,让我们看看你已经学会的一些误解:

  • 静态仅适用于生命周期-是的。它没有说明它存储的时间或位置,只是说当你要求它时它是可用的。兼容的运行时可以自由使用它想要的任何内存,甚至永远不会加载内存中的字段(例如,将它保存在映像中,映像无论如何都已经在内存中了)
  • 静态将在生命周期内堆起来-很可能,是的。但它不是规范的一部分,只要有适当的保证,兼容的运行时可以将它存储在任何地方,或者根本不存储。此外,不要忘记"终身"的意思是"至少在AppDomain的生命周期内";当卸载域时,它可能被释放,也可能不被释放
  • 静态值类型将在生命周期内保留在堆栈上-很可能不会。同样,这是一个实现细节,但堆栈的语义与静态值的语义完全不同。下一点会给你更多的理由:
  • 加载assambly时,将调用所有静态构造函数,包括静态字段-没有。没有这样的要求,也没有这样的保证。如果你依赖这一点,你的程序就会崩溃(我以前见过很多次)。同样,这是一个实现细节,但在当前的MSCLR实现中,静态往往是在它们自己的堆中分配的,并且在需要定义它们的类型之前需要一段时间。如果在静态构造函数中抛出异常,您可以很容易地看到这一点——它将导致TypeLoadException,很可能是在首先引用该类型的方法中(不用说,这可能会使调试静态变得棘手)
  • 引用类型放在堆上,值类型放在堆栈上-不。这混淆了机制和语义。两者之间唯一的区别是它们的语义——其他一切都取决于实现。如果运行时可以为堆栈上的引用类型保留引用语义,那么这是完全有效的。即使使用当前的MSCLR运行时,值类型也会一直存储在堆中——例如,只要它们被装箱,或者是引用类型的成员

有些人可能会感到困惑。有些人不理解合同和实际实现之间的区别。有些人根本不知道自己在说什么。我希望有一个简单的方法来知道哪个是哪个,但没有。如果有疑问,您可以参考C#/CLR规范,但这只是告诉您合同,而不是实际情况。

托管内存的全部意义在于,您不应该关心这些实现细节。当然,就像任何抽象一样,它会泄漏——通过所有不同的层和抽象,了解事情的真实情况,直到CPU微入侵、内存缓存等,都是有意义的。但这并不是所依赖的——实现可以随时更改,而且在过去也有很多次。

每当一个进程被加载到RAM中时,我们可以说内存是大致分为三个区域(在该过程中):Stack、Heap、,和静态(在.NET中,它实际上是Heap内部的一个特殊区域仅被称为高频堆)。

静态部分包含"静态"成员变量和方法。什么究竟是静态的?那些不需要要创建的类的实例被定义为静态

点击此处阅读更多信息。

创建了一个类实例,初始化了所有静态成员。

静态类的成员通常存储在堆上,值类型的成员通常保存在堆栈上。

不一定是这样,你可以阅读这个博客了解更多信息。

它来自C#的一位语言设计师Eric Lippert。

博客显示,与正常知识相反,它不确定值类型是否在堆栈上,引用类型是否在堆上,但它们通常都在。

只是规范中没有具体说明。

最新更新