C#堆与栈

时间:2022-03-27 09:18:45

解释1、栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义;堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小

解释2、

存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护。

而堆是无序的,他是一片不连续的内存域,有用户自己来控制和释放,,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收。

引用类型总是存放在堆中。

值类型和指针总是放在它们被声明的地方。

调用方法:系统先将一段编码(堆的首部地址)放到栈上,紧接着放置方法的参数。然后代码执行到方法时,查找栈中放该堆首部地址的所有参数,并通过堆的首部地址来控制堆。

引用类型:总是放在堆当中。

当我们使用引用类型时,实际上只是在处理该类型的指针。而非引用类型本身,使用值类型的话则是使用其本身。

解释3、

线程堆栈:简称栈 Stack
托管堆: 简称堆 Heap

使用.Net框架开发程序的时候,我们无需关心内存分配问题,因为有GC这个大管家给我们料理一切。如果我们写出如下两段代码:
代码段1:

public int AddFive(int pValue)
           {
                int result;
                 result = pValue + 5;
                return result;
           }

代码段2:

public class MyInt
           {         
             public int MyValue;
           }

public MyInt AddFive(int pValue)
           {
                 MyInt result = new MyInt();
                 result.MyValue = pValue + 5;
                return result;
           }

问题1:你知道代码段1在执行的时候,pValue和result在内存中是如何存放,生命周期又如何?代码段2呢?
要想释疑以上问题,我们就应该对.Net下的栈(Stack)和托管堆(Heap)(简称堆)有个清楚认识,本立而道生。如果你想提高程序性能,理解栈和堆,必须的!
本文就从栈和堆,类型变量展开,对我们写的程序进行庖丁解牛。
C#程序在CLR上运行的时候,内存从逻辑上划分两大块:栈,堆。这俩基本元素组成我们C#程序的运行环境。

一,栈 vs 堆:区别?

栈通常保存着我们代码执行的步骤,如在代码段1中 AddFive()方法,int pValue变量,int result变量等等。而堆上存放的则多是对象,数据等。(译者注:忽略编译器优化)我们可以把栈想象成一个接着一个叠放在一起的盒子。当我们使用的时候,每次从最顶部取走一个盒子。栈也是如此,当一个方法(或类型)被调用完成的时候,就从栈顶取走(called a Frame,译注:调用帧),接着下一个。堆则不然,像是一个仓库,储存着我们使用的各种对象等信息,跟栈不同的是他们被调用完毕不会立即被清理掉。

如图1,栈与堆示意图

(图1)

栈内存无需我们管理,也不受GC管理。当栈顶元素使用完毕,立马释放。而堆则需要GC(Garbage collection:垃圾收集器)清理。


二,什么元素被分配到栈?什么被分配到堆?

当我们程序执行的时候,在栈和堆中分配有四种主要的类型:值类型,引用类型,指针,指令。

值类型:
在C#中,继承自System.ValueType的类型被称为值类型,主要有以下几种(CLR2.0中支持类型有增加):
    * bool
    * byte
    * char
    * decimal
    * double
    * enum
    * float
    * int
    * long
    * sbyte
    * short
    * struct
    * uint
    * ulong
    * ushort

引用类型:
以下是引用类型,继承自System.Object:
    * class
    * interface
    * delegate
    * object
    * string