C#内存管理-栈堆/回收器托管/非托管资源释放/指针的应用

本文详细探讨了C#中的内存管理,包括栈内存的上往下增长和自动释放,托管堆的下往上增长及按需释放,垃圾回收器的工作原理和手动调用System.GC.Collect(),如何通过IDisposable和析构函数释放非托管资源,以及指针在直接访问内存和应用方面的介绍。
摘要由CSDN通过智能技术生成

1.栈内存-从上往下增长,释放时从下部的末尾出栈

.net 5中栈好像也是从下往上增长了,释放时从上部顶端出栈。
栈类型数据,整体是从进程空间中的栈内存资源的最大地址处开始分配栈内存的,栈指针总是指向已用地址更小的内存地址上,下一个为空闲内存地址。当变量出了作用域时候,栈内存就会释放,栈指针上移到非空闲地址的小地址上,若再进来变量就会覆盖之前不用了的地址内存区域。
     栈内存分配是对整个变量来说的,具体变量内部十六进制数据排序主机中基本是小端模式低地址在低内存地址中。栈上变量或结构体生命期是嵌套的,栈中大小是有限制的。

2.托管堆-从下往上增长,释放时是按需进行的

堆是托管堆,可以分配更大更易于手动控制的内存,堆是一开始在低内存地址的,上层的空间才是空闲的,向上生长的和栈刚好相反,引用对象指向堆中地址的低地址。一个堆内存有一个栈引用持有,当栈引用超过生命期的时候,堆内存减少引用计数,垃圾回收器会隔一段时间扫描下堆内存将引用计数为0的堆内存清理掉。
   堆内存分配也是对整个对象来说的,具体对象内部数据排序十六进制排序主机是小端模式数据的低位存放在低地址。堆中对象生命期看引用的生命期还有回收器回收周期来决定,堆内存可以获得比较大的易于控制的内存空间。

3.垃圾回收器工作方式 -会重新挪动整理和修改对象的引用地址/System.GC.Collect()

最近使用最多和大堆不放置总堆中提高性能,System.GC.Collect()手动调用垃圾回收,不保证一次回收完但是也很有作用了。
在CC++的旧堆中,如果删除了不需要的内存,那么堆内存区域中就会存在分散的非空闲和空闲内存块,运行越久分配越频繁,那么产生的内存碎片越多,每次申请新的内存空间都要遍历整个堆。但是C#CRL托管堆中垃圾回收器每次扫描释放完一次托管堆资源,就会把其它还在生命期内的对象移动会堆的底部(因为是从下往上增长的),整理一遍(总的小堆内存中,大堆资源不会移动整理),再次形成连续的内存块,垃圾回收器会将这些对象的所有引用都用新的地址来更新,垃圾回收器的这个整理堆内存操作是托管堆和非托管的旧堆的区别所在。尽管压缩堆,修改它移动的所有对象引用,致使性能降低,但是.net中实例化对象申请内存空间和访问速度都会比较快,.net认为压缩堆是值得的。
垃圾回收器在.net CRL认为需要调用它时候才调用,但是也可以通过手动调用System.GC.Collect()方法强迫回收器在代码中运行,例如一下子取消很多对象的引用,例如换关卡时候,就适合调用,但是垃圾回收器不能保证在一次垃圾回收过程中,将所有未引用的对象都从堆中删除。
.net垃圾回收运行时候,应用程序不能继续运行,因此会影响性能。但是.net垃圾回收使用了一些算法和架构设计来提高性能,算法是指FIFO原则,刚进来的对象肯定很多很快被回收,所以.net托管堆是往上增长的,最新的总是放置在最上面,删除得也多,所以降低了托管堆移动的概率。有趣的是,在给对象分配内存空间时,如果超出第0代(最上层区域)对应的部分容量,或者调用了GC.Collect()方法,就会进行垃圾回收。
架构是说大堆资源85000Byte,83kb的堆资源那么会放置在特殊大堆对象的堆上,而不是总堆中因此不会挪动大堆对象压缩,因为大堆对象挪动比较耗时,因此提高了垃圾回收的性能。

4.释放非托管的资源

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值