所有静态成员都存储在哪里? [英] Where are all the static members stored?

查看:262
本文介绍了所有静态成员都存储在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习C#如何管理内存.我被静态元素所困扰,我阅读了许多有关此主题的博客和文章,但是找不到一个令人满意的答案.

I'm trying to learn how C# manages memory. I am stuck on static elements, I read numerous blogs and articles on this subject, but I cannot find a quite satisfactory answer.

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

Let's define a code block to help find the answer.

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

在大家分享您的答案之前,让我分享我对这个问题知道的发现.随时同意或不同意,并帮助我找到正确的答案.

Before you guys share your answer, let me share my findings that I know about this subject. Feel free to agree or disagree and help me to find correct answer.

  • 静态只是一生.
  • 静态引用类型(myStr)将在生命周期内不断堆积.
  • 静态值类型(myInt)将终身使用.

让我感到困惑的是,我在互联网上找到了有关该主题的一些答案.

What confuses me, are some answers that I found on internet, on this subject.

困惑数字1:

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

When your program starts, it loads all the related assemblies into an AppDomain. When the assembly is loaded, all static constructors are called, including static fields. They will live in the there, and the only way to unload them, is to unload the AppDomain.

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

In above lines, it is mentioned explicitly that all static elements stored on AppDomain. Then why everybody on internet says 'Static' elements are stored on heap/stack?

困惑编号2:

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

Every static variable is stored on the heap, regardless of whether it's declared within a reference type or a value type.

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

If every static variable stored on heap. Then why some folks says that value type static variable are stored on stack?

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

Please help to connect my dots to understand memory management of static variables in C#. Thank you very much for your precious time :)

推荐答案

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

First, note that all of this is an implementation detail. The only thing the runtime guarantees is:

  • 当您请求一个静态字段时,它就在那里
  • 在使用类型之前,静态构造器会在某个时候执行

就是这样.其他所有内容都是实现细节-规范不关心堆栈,堆或其他任何内容.这取决于运行时的实现,并且有效的运行时可以将所有内容(如果需要)放在堆栈上,也可以放在堆上.而且不要忘记寄存器.

That's pretty much it. Everything else is an implementation detail - the specification doesn't care about stack, heap or anything else. It's up to the implementation of the runtime, and a valid runtime could put everything on the stack, if it so desired, or on the heap. And don't forget registers.

现在,让我们看看您已经设法弥补的一些误解:

Now, let's see some of the misconceptions you already managed to pick up:

  • 静态信息是一生不变的-是的.它没有说明存储时间和位置,只是在您需要时可用.符合条件的运行时可以自由使用所需的任何内存,甚至从不将字段加载到内存中(例如,将其保留在映像中,而映像已经存在于内存中)
  • 静电将持续一生 -很可能,是的.但这不是规范的一部分,兼容的运行时可以将其存储在任何需要的地方,或者只要有适当的保证就可以存储在任何地方.另外,请不要忘记在生命周期内"的意思是至少在AppDomain的生命周期内";卸载域后,它可能会释放也可能不会释放.
  • 静态值类型将持续使用一生 -很可能不会.再次说明实现细节,但是堆栈的语义与对静态值有意义的语义完全不同.接下来的一点将为您提供更多原因:
  • 加载临时表时,将调用所有静态构造函数,包括静态字段.-否.没有这样的要求,也没有这样的保证.如果您依赖于此,您的程序将会崩溃(而且我之前已经看过很多次了).再次说明实现细节,但是在当前的MSCLR实现中,静态变量倾向于在自己的堆中分配,并且需要在定义它们的类型之前的一段时间.如果在静态构造函数中引发异常,则很容易看到这一点-它会导致TypeLoadException,最有可能是在首先引用该类型的方法中产生的(不必说,这会使调试静态变量变得棘手).
  • 引用类型放在堆栈上,值类型放在堆栈上.-否.这会使机制与语义混淆.两者之间的唯一区别是它们的语义-其他一切取决于实现.如果运行时可以在堆栈上保留引用类型的引用语义,那将是完全正确的.甚至在当前的MSCLR运行时中,值类型也始终存储在堆中-例如,将它们装箱时或引用类型的成员存储在堆中.
  • Static is just for the lifetime - yes. It doesn't say anything about when or where it is stored - just that it's available when you asked for it. A compliant runtime is free to use whatever memory it wants, or even never to load the fields in memory (e.g. keeping it in the image, which is already in memory anyway)
  • Static will go on heap, for life time - most likely, yes. But it's not part of the specification, and a compliant runtime can store it wherever it wants, or nowhere at all, as long as the proper guarantees hold. Also, don't forget that "for life time" means "at least for the life time of the AppDomain"; it may or may not be released when the domain is unloaded.
  • Static value type will go on stack, for life time - most likely, no. Again, an implementation detail, but the stack has completely different semantics than what makes sense for a static value. And the next point will give you more of a reason why:
  • When the assambly is loaded, all static constructors are called, including static fields. - No. There is no such requirement, and no such guarantee. If you rely on this, your program is going to break (and I've seen that plenty of times before). Again, an implementation detail, but in the current MSCLR implementations, statics tend to be allocated in a heap of their own, and some time before the type they are defined in is needed. You can easily see this if you throw an exception in a static constructor - it will cause a TypeLoadException, most likely in a method that first references the type (needless to say, this can make debugging statics tricky).
  • Reference types go on the heap, value types go on the stack. - No. This is confusing the mechanism with the semantics. The only difference between the two are their semantics - everything else is up to the implementation. If a runtime can preserve reference semantics for reference types on the stack, that's perfectly valid. And even with current MSCLR runtimes, value types are stored on the heap all the time - whenever they are boxed, or members of a reference type, for example.

有些人可能会感到困惑.有些人不了解合同与实际实现之间的区别.有些人根本不知道他们在说什么.我希望有一个简单的方法来知道哪个是哪个,但是没有.如果有疑问,可以转到C#/CLR规范,但这仅告诉您有关合同的信息,而不是实际情况.

Some folks may be confused. Some don't understand the difference between the contract, and the practical implementations. Some simply don't know what they're talking about. I wish there was an easy way to know which is which, but there isn't. If in doubt, you can go to the C#/CLR specifications, but that only tells you about the contract, not the practical reality.

托管内存的全部目的是,您不应该关心这些实现细节.当然,就像任何抽象一样,它也会泄漏-通过所有不同的层和抽象,知道事情的真相,直到CPU微指令,内存缓存等都是有意义的.但是 没什么可依赖的-实现可以随时更改,并且过去有很多次.

The whole point of managed memory is that you aren't supposed to care about these implementation details. Of course, like any abstraction, it leaks - and it makes sense to know how things really are, down to the CPU micro-intructions, memory caching etc., through all the various layers and abstractions. But it's nothing to rely on - the implementation can change at any time, and it has many times in the past.

这篇关于所有静态成员都存储在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆