2017-07-25 85 views
-1

我正在阅读有关Dispose模式并碰到如何memory is allocated。以下是http://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-memory/的报价。如果大部分数据都堆在堆栈上,堆栈内存的主要重要性/作用是什么?

内存分配
....
....
唯一的例外是属于引用类型值类型 - 例如用户类的Id特性的推移的堆以及User类本身的实例。

这里也提到了Stack Overflow的问题。 memory allocation for value type inside reference type in .net

我的理解是,所有值类型与它们声明的位置无关,都会叠加。现在看起来错了。在下面的代码中,i将堆积如山;根据链接不在堆栈上。这是因为MyClass是引用类型,它将与堆一起堆栈,并且它的所有值类型。

class MyClass() 
{ 
    int i = 5; 
} 

好吧,所以只有值类型那些不是类的一部分,然后转到堆栈内存。对?但是,像C#这样的DotNet语言中的几乎所有内容都在课堂内。那么到底什么去堆栈内存?

这个answer解释了什么值类型堆。

如果是这种情况,那么堆栈内存上的内存很少甚至几乎没有。

我怀疑我误解了一些东西。

如果几乎所有的数据都进入堆内存,我不明白堆栈内存的重要性和作用。

请解释。


以下两篇文章以简单的方式解释了关于内存管理的很多内容。

https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail-part-one/

https://blogs.msdn.microsoft.com/ericlippert/2009/05/04/the-stack-is-an-implementation-detail-part-two/

+0

堆栈主要用于局部变量并跟踪调用树中的这些变量。 – juharr

+2

阅读Eric Lippert的[堆栈是一个实现细节](https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail-part-one/) 。 –

+0

堆栈是有用的,因为它推动和弹出。这是不小的优势。这就是为什么*是堆栈。它*发生*有时也在内存分配方案中有用 - 并从那里Eric Lippert的解释进来。 –

回答

9

不要把它想成 “栈” 和 “堆”。将其想象为短期记忆长期记忆。现在很容易知道堆栈上发生了什么以及堆中发生了什么。 变量的生存期是否比当前方法的激活时间长?如果是的话,那么它不是短命的,而必须堆积如山。如果是,那么可以进栈。

例如:

class C { 
    void M() { 
    string s = Whatever(); 
    Something(s); 
    } 
} 

局部变量s可以去在短期池,因为它不会持续长于方法激活。

现在,你可能会说等一下,string是一个引用类型,所以它肯定会堆在堆上。不,它不是。 字符串放在堆上,但该变量不包含字符串。字符串是一个引用类型,所以该变量包含引用引用可以在栈上。它是指的是在堆上,但参考本身是一个值,并且可以在堆栈上。

因此,不要以为任何东西的类型决定了它的存储位置。该类型是无关紧要的。价值类型或参考类型的变量如果寿命短,可以在短期内汇入,如果不是,则必须长期汇入。

现在来谈谈

class C { 
    void M() { 
    int i = Whatever(); 
    X(() => i) 
    } 
} 

现在我可以进入堆叠?编号X可以存储传入的委托的副本,并且该委托需要知道i的值,因此该变量需要比方法M的激活寿命更长,因此i会长期存在。 i在这里堆。

同样,它是一个int的事实是完全不相关的。这是一个变量,它生活很长时间,所以它堆积如山。

怎么样一个类的字段或数组的元素?那些是变数。只要类实例或数组实例存在,它们就会生活,因此它们的生命周期是不可预测的,因此它们会长期存在。

为什么我们有一个短期池和一个长期池?因为短期池的垃圾回收器是极其便宜的相对于长期池的垃圾回收器而言便宜且便宜。因此,我们希望可以选择在短期池中生成变量 - 这是当它们的寿命是

+0

“......它指的是堆......” - 为什么?它总是保证在堆中分配吗?如果我有一个'Tuple '(引用类型),为什么需要在堆中分配? –

+2

@LucaCremonesi:因为所提到的事情*不知道有一个短的生命*。现在,有些场景我们可以知道在方法中创建了一个特定的引用,从不会转义该方法,因此在该方法返回后仍未使用。在这些情况下,CLR *可以生成对堆栈中某些东西的引用。目前的实现不这样做;只有一个分配器和收集器用于参考类型会更便宜,更容易。但是*原则上*不反对参考类型的短命例。 –