C#的内存分配与管理

前言:前面的文章已经在内存的管理方面说的比较多了,这里再补充一下关于C#的内存分配与管理。前面的两篇文章参见:

一文详解堆栈(二)——内存堆与内存栈

一文读懂C#的 堆、栈、值类型、引用类型

一、C#的内存分类

由于C#是一种托管语言,它的垃圾回收机制(GC)是由.net平台负责的,加之C#语言并没有指针,所以我们在使用过程中极少会考虑到内存使用状况以及项目在运行过程中是如何进行内存管理的。但是,C#只是在内存管理方面对程序员隐藏了,并不代表它不涉及这些东西,甚至其内部内存管理或许比自己手动管理更加复杂。

参考前面文章中的内存分类——四分类,本文会依据自己的理解,从这四个分类来说明。

1、代码区

 

2、线程栈  

C#程序在程序运行的时候,每个线程(Thread)都会维护一个自己的专属线程堆栈。此即为“栈”,或者称之为“线程栈”

值类型存储在线程栈。栈由操作系统进行管理,不受GC管理,当值类型不在其作用域(主要是指其所在函数内)时,其所占栈空间自动释放。栈的执行效率是非常高的。

3、托管堆

当CLR载入内存之后,会初始化两个托管堆,

  1. 一个大对象堆(LOH –large object heap)
  2. 一个小对象对(SOH – small object heap)
  3. GC堆


(1)小对象堆(SOH)

对于SOH,对象在执行一次垃圾回收之后,会进入到下一代。也就是说如果在第一次执行垃圾回收时,存活下来的对象会进入第1代,如果在第2次垃圾回收之后该对象仍然没有被当作垃圾回收掉,它就会成为2代对象;2代对象就是最老的对象不会在提升代数。从代的角度看,大对象属于2代对象,因为只有在2代回收时才会处理大对象。

(2)大对象堆(LOH)
用于分配大对象实例。大对象就是大小大于85000字节(约为83k)的实例对象。大对象分配在LOH上,不受GC控制,不会被压缩,只有在完全GC回收(只有在2代回收时才会处理大对象)时才会被回收。

(3)GC堆
用于分配小对象实例。所谓小对象就是大小小于85000字节(约为83k)的实例对象。GC堆分三代垃圾进行管理,当进行GC操作(垃圾回收)时,垃圾收集器会对GC堆进行压缩回收。

 

4、全局数据区

 

       全局变量、常量、静态类静态成员(静态变量、静态方法),都存放在全局区,而它们的地址放在声明时变量(在代码区)开辟在栈区的内存中。(这些地址都是在程序运行时最先压栈的,这点很重要)

       全局变量和静态类、常量、静态成员,都是在全局区,但是它们的地址仍放在栈区,为什么会保存住呢?因为在.net程序编译时这些静态和全局都是最先编译的,所以最先压栈,那么也就只能等程序结束时才会弹栈,所以全程可用。缺点就是启动慢、编译时间长;当然优点也有,如常说的,静态类常用于窗体传值和实现单例模式,这就得益于它的一次编译全程可用。

(这就是为什么静态类,静态数据可以全程使用的原因了,因为它们最先入栈,最后出栈

        所以全局和静态上面说过,会在程序运行结束时才会被释放和回收,所以应限制使用全局变量、常量、和静态变量和静态类,否则程序负荷高。
 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值