带你复习c# 托管和非托管资源

 更新时间:2020年11月3日 15:20  点击:1621

前言

c# 托管和非托管比较重要,因为这涉及到资源的释放。

现在只要在计算机上运行的,无论玩出什么花来,整个什么概念,逃不过输入数据修改数据输出数据(计算机本质),这里面有个数据的输入,那么我们的内存有限啊,这里面就牵扯到数据释放。

看下c# 的垃圾回收是怎么样的。

了解垃圾回收之前首先要了解数据,了解数据需要了解数据类型啊,数据类型分为值类型还有引用类型。

windows 使用一个虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址上,这些任务完全由windows 在后台管理。我们的程序运行在操作系统上,那么我们作为程序员关系的就是这个虚拟寻址系统。

这东西有什么用呢?

比如32位系统中,每个进程所占用的最多4G(4G这样来的,2^32,4个字节),那么这个程序如果进行管理的这4G,它不需要知道在硬件地址是多少。

比如这个进程申请了1k内存,那么这个进程管理的实际是从0到1k的虚拟内存,而不需要知道这个硬件物理内存地址是多少,有一个可以直接证明的就是我们写c++输出指针的时候,发现指针输出1千多,

你觉得可能是物理内存地址的1千多吗?默默的打开资源管理看看现在占用多少内存。

默认情况下,32 位计算机上的每个进程都具有 2 GB 的用户模式虚拟地址空间。这里解释一下,每个进程2个G是虚拟地址,就是在这个进程维护一个2G的虚拟地址,并不是实际占有2G的硬件内存地址。

盗一张图:

虚拟地址有三种状态:

状态 描述
Free 该内存块没有引用关系,可用于分配。
保留 内存块可供你使用,并且不能用于任何其他分配请求。 但是,在该内存块提交之前,你无法将数据存储到其中。
已提交 内存块已指派给物理存储。

那么这个虚拟内存上又分了堆和栈,栈上存储值类型,堆上存储引用类型。

他们的存储方式不一样。

下面是栈:

栈是这样子的先用高位后用低为,比如申请80000,先用的就是80000 直到为0为止。

{
 int a=10;
 double b=100.0;
}

如上图,80000用完了,这时候栈指针指向80000。

现在int a了,int是4个字节,这时候栈指针减4,到79996这个位置。

然后是double,double 为8个字节,这时候栈指针减8,以此类推。

然后如果变量超出作用域,那么这个时候就会被垃圾回收,栈指针增加8,然后增加4。(记得栈指针增加的时候[垃圾回收]并不会去把已经使用的地址重置为0,只有类型申明的时候才重置为0,然后再赋值)

下面是引用类型:

堆是这样子的,已用的内存地址小,空闲的内存地址大。

举个栗子:

{
 student a;
 a=new student;
}

首先运行student a,这个时候存储的是引用地址,也就是4个字节,存放在栈上。

然后运行a=new student(),首先假设student使用64个字节,那么在堆上就申请连续的64个字节,然后把首地址传递赋值给a。

上面非常大的程度简化了程序的内存分配,引用类型垃圾回收的一个简化版就是——当一个引用变量超出作用域的时候,它会从栈中删除,但是引用对象的数据保存在堆中,只有没有任何一个引用变量指向引用对象的时候那么这个引用对象才会回收。

好的,知道了数据存储是怎么样的,来看一下垃圾回收吧。

正文

关于垃圾回收,.net 文档是这样介绍的。

.NET 的垃圾回收器管理应用程序的内存分配和释放。
每当有对象新建时,公共语言运行时都会从托管堆为对象分配内存。
只要托管堆中有地址空间,运行时就会继续为新对象分配空间。
不过,内存并不是无限的。 垃圾回收器最终必须执行垃圾回收来释放一些内存。
垃圾回收器的优化引擎会根据所执行的分配来确定执行回收的最佳时机。
执行回收时,垃圾回收器会在托管堆中检查应用程序不再使用的对象,然后执行必要的操作来回收其内存。

那么什么时候垃圾回收呢?

1.系统具有低的物理内存。 这是通过 OS 的内存不足通知或主机指示的内存不足检测出来。

2.由托管堆上已分配的对象使用的内存超出了可接受的阈值。 随着进程的运行,此阈值会不断地进行调整。

3.调用 GC.Collect 方法。 几乎在所有情况下,你都不必调用此方法,因为垃圾回收器会持续运行。 此方法主要用于特殊情况和测试。

第三个.net 平台会帮我们处理,第二个托管堆会帮我们自我调整,关键是第1个如何物理内存不足的时候就会被回收,一般时候整个操作系统内存占用在15%-30%之间都是可调控的,基本不用担心这个问题,但是为了容灾性代码依然需要做一些判断处理。

垃圾回收的回收机制是通过代数来实现。

为优化垃圾回收器的性能,将托管堆分为三代:第 0 代、第 1 代和第 2 代,因此它可以单独处理长生存期和短生存期对象。

第 0 代。 这是最年轻的代,其中包含短生存期对象。 短生存期对象的一个示例是临时变量。 垃圾回收最常发生在此代中。

第 1 代。 这一代包含短生存期对象并用作短生存期对象和长生存期对象之间的缓冲区。

第 2 代。 这一代包含长生存期对象。 长生存期对象的一个示例是服务器应用程序中的一个包含在进程期间处于活动状态的静态数据的对象。

垃圾回收中未回收的对象也称为幸存者,并会被提升到下一代:

第 0 代垃圾回收中未被回收的对象将会升级至第 1 代。
第 1 代垃圾回收中未被回收的对象将会升级至第 2 代。
第 2 代垃圾回收中未被回收的对象将仍保留在第 2 代。

因为第 0 代和第 1 代中的对象的生存期较短,因此,这些代被称为“暂时代”。

垃圾回收的过程:

标记阶段,找到并创建所有活动对象的列表。

重定位阶段,用于更新对将要压缩的对象的引用。

压缩阶段,用于回收由死对象占用的空间,并压缩幸存的对象。 压缩阶段将垃圾回收中幸存下来的对象移至段中时间较早的一端。

因为第 2 代回收可以占用多个段,所以可以将已提升到第 2 代中的对象移动到时间较早的段中。 可以将第 1 代幸存者和第 2 代幸存者都移动到不同的段,因为它们已被提升到第 2 代。

然后后台垃圾回收、大型对象堆、被动回收、延迟模式等可以作为了解。

与我们写代码息息相关

垃圾回收机制与我们写代码息息相关的部分是:

  1. 强引用和弱引用
  2. 针对共享 Web 承载优化
  3. 垃圾回收和性能
  4. 应用程序域资源监视

后续一节整理一下。

以上就是带你复习c# 托管和非托管资源的详细内容,更多关于c# 托管和非托管资源的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25