.NET的托管堆中是否可能出现内存泄漏现象
本文节选自《.NET程序员面试指南》一书

这一问题的难度比较大,主要注重的是应聘人员的程序开发经验。如果切身经历过一些内存泄漏的情况,那应聘者将比较容易回答此类问题。无论如何,读者至少应该了解,即使在拥有垃圾处理机制的托管堆上,仍然是可能发生内存泄漏现象的。
  所涉及到的知识点
•    什么是内存泄漏
•    一些常见的导致托管堆内存泄漏的情况
  分析问题
    在一些不规范的编码情况下,即使是拥有垃圾回收和内存管理机制的托管堆上,仍然可能出现内存泄漏。首先读者需要了解什么是内存泄漏。
    内存泄漏是指内存空间上产生了不再被实际使用却又不能被分配的内存,内存泄漏的意义很广泛,例如程序无意义地保持对象内存、内存碎片、不彻底的对象释放等都属于内存泄漏现象。内存泄漏将导致主机的内存随程序的运行而逐渐减少,无论内存泄漏的具体形式如何,它的危害都是显而易见的,所有的内存泄漏都是需要程序员努力避免的。
按照内存泄漏的定义,大部分时候.NET的托管堆中存在着短暂的内存泄漏情况,那是因为对象一旦不被使用后,需要等到下一个GC时才能被释放。这里,笔者将举出其他几种对系统危害更大的内存泄漏情况:
1)大对象的分配
.NET中所有的大对象将分配在托管堆内一个特殊的区域,这里暂时称呼它为“大对象堆”。在回收大对象堆内的对象时,其他的大对象不会被移动,这是考虑到大规模地移动对象需要耗费过多的资源。这样,在程序过多地分配和释放大对象之后,就会产生很多内存碎片。
,随着对象的分配和释放不断进行,在不进行对象移动的大对象堆内,将不可避免地产生小的内存碎片。程序员对此能做的就是尽量减少大对象的分配次数,尤其是那些作为局部变量的,将被大规模分配和释放的大对象,典型的例子就是String类型,关于String的使用在后续章节将有详细的叙述。
2)不恰当地保存根引用
最简单也最常见的错误做法可能就是不恰当地把一个对象申明为公共静态变量,一个公共的静态变量将一直被GC视为一个在使用的根引用,而更糟糕的情况是,当这个对象内部还包含更多的对象引用时,这些对象同样不会被释放。看一段简单的代码:代码3-19。
代码3-19  保存根引用:RefRoot.cs
namespace NET.MST.Third.RootRef
{
    public class RefRoot
    {
        //这里是一个占用大量内存的成员
        public String[] BigMembor;
        public RefRoot(String content)
        {
            //初始化大对象
            BigMembor = new String[1000];
            for (int i = 0; i < BigMembor.Length; i++)
                BigMembor[i] = content;
        }
    }
    public class MainClass
    {
       //公共静态大对象
        public static RefRoot bigobject = new RefRoot("aaa");
        static void Main()
        {
            Console.Read();
        }
    }
}
在代码3-19中,MainClass定义了一个公共静态的大对象,这个对象将直至程序运行结束后才会被GC释放。这一段代码的设计是否成功将取决于这个公共静态变量被使用的频率以及业务逻辑,如果在整个程序中各个类型不断地使用这个静态成员,那这样的设计有助于减少大对象堆内的内存碎片,但如果整个程序极少地甚至于只有一次使用了这个成员,那考虑到它占用的内存会影响整体系统的性能,设计时应该考虑把他设计成实例变量,以便于GC能够及时地释放它。
这里仍然只从性能的角度考虑问题,实际的设计情况不仅需要考虑性能,还需要考虑程序的和架构和可扩展性。
3)3)不正确的Finalize方法
在前述章节中笔者已经介绍了,Finalize方法由一个专用的线程进行调用,微软并没有公开这部分具体的调度算法,但是有一点却是肯定的,不正确的Finalize方法将导致Finalize方法不能被正确执行,系统中所有的Finalize方法不能被正确执行时,包含它们的对象也只能驻留在托管堆内不能被释放,这样的情况将会导致严重的后果。
Finalize方法应该只致力于快速而简单地释放非托管资源,并且尽可能快地返回。不正确的Finalize方法可能包含这样的代码:
•    没有保护地写文件日志
•    访问数据库
•    访问网络
•    把当前对象赋给某个存活的引用
当Finaize方法访问文件系统、数据库系统或者网络时,将会有资源争用和等待的潜在危险。试想一个试图不断尝试访问离线数据库的Finalize方法,将会在长时间内不会返回,这不仅影响了本身对象的释放,也使得排在Finalize方法队列中的所有后续对象得不到释放,这个连锁反应将很快造成内存耗尽。
而另外一种危险的代码是在Finalize方法中把对象自身又赋给了另外一个存活的引用,这时对象内的一部分资源已经被释放了,而另外一部分则没有,这样一个对象被再次激活后,将导致不可预知的后果。
  答案
.NET的托管堆内可能出现严重内存泄漏现象,主要产生原因有:大对象的频繁分配和释放、不恰当地保留根引用和错误的Finalize方法。


5}J J l/m8rsm13164110
f.M T6?+~ Q13164110【书名】.NET程序员面试指南
【作者】朱毅 等 编著
【ISBN】978-7-121-07675-6
【出版社】电子工业出版社
【出版日期】2008年12月
【宣传语】
从面试的角度来梳理.NET程序员的技术功底。
以项目开发经理的眼光来审视编程知识的掌握。
【内容简介】
本 书着重针对.NET技术职位的应聘者,在.NET框架各个技术类别中,选取最常出现在.NET面试中的问题,进行分析和解答,同时解释和剖析和该问题相关 的.NET机制原理,帮助读者达到知其然更知其所以然的程度。本书几乎包揽了所有常见的面试题,从基础知识、数据库,再到比较流行的XML、测试方法和算 法,是目前市场上唯一一本面试试题集锦。
全书配合了大量的图例及代码说明,非常适合正打算参加.NET技术职位的应聘和希望梳理.NET框架下技术点的读者阅读

.NET的托管堆中是否可能出现内存泄漏现象相关推荐

  1. 在java中会存在内存泄漏吗?

    ● 请问,在java中会存在内存泄漏吗?请简单描述一下. 考察点:内存 参考回答: Java中的确存在Java的内存泄漏, 并且事态可以变得相当严重 Java garbage collector自动释 ...

  2. 实例解析网络编程中的另类内存泄漏

    本文分享自华为云社区<[网络编程开发系列]一种网络编程中的另类内存泄漏>,作者:架构师李肯. 1 写在前面 最近在排查一个网络通讯的压测问题,最后发现跟"内存泄漏"扯上 ...

  3. 微信小程序开发过程中出现的内存泄漏问题

    微信小程序开发过程中出现的内存泄漏问题 问题描述 微信小程序项目中,有两个页面多次来回切换,(我这个项目数因为 有 再来一次,和 回顾本次 的功能 所以要在答题页和分数页来回切换)就会报错 VM333 ...

  4. windows2003中未分页内存泄漏导致服务器不稳定的解决方法

    2015年天互进行了内部员工干货分享计划,让销售.技术.客服.市场.行政五大体系的员工把自己工作中的干货内容分享给大家,共同提高业务能力和工作效率.本篇内容来自虚拟产品部姚运的技术日志分享," ...

  5. polkits存在内存泄漏现象

    服务器中polkits内存占用很大,经过查阅资料发现可能是polkits的内存泄漏导致,这个可以作为后续服务器内存分析的一个参考. polkits存在内存泄漏现象.​ 参考: Bug 29069 -  ...

  6. 什么是堆,栈,内存泄漏和内存溢出?

    heap:是由malloc之类函数分配的空间所在地.地址是由低向高增长的. stack:是自动分配变量,以及函数调用的时候所使用的一些空间.地址是由高向低减少的. 一.预备知识-程序的内存分配 一个由 ...

  7. c++面向对象高级编程 学习三 堆、栈和内存泄漏

    栈,是存在于某作用域的一块内存空间.在函数体内声明的任何变量,其所使用的内存空间均来自于栈. 堆,是指由操作系统提供的一块global内存空间,程序可动态分配获得若干内存空间块. new操作符生成的对 ...

  8. Java中会存在内存泄漏吗,请简单描述。

    内存泄漏是指不再被使用的对象或者变量一直被占据在内存中. 理论上来说,Java是有GC垃圾回收机制的,也就是说,不再被使用的对象,会被GC自动回收掉,自动从内存中清除. 但是,即使这样,Java也还是 ...

  9. JS中常见的内存泄漏及识别方式

    JavaScript常见的内存泄漏及识别方式 1.什么是内存 2.什么是内存泄漏 3.内存泄漏导致的后果 4.常见的内存泄漏 (1)全局变量引起的内存泄漏 (2)闭包引起的内存泄漏 (3)被遗忘的定时 ...

  10. java内部类内存泄漏,Android中常见的内存泄漏和解决方案

    什么是内存泄漏? 简单点说,就是指一个对象不再使用,本应该被回收,但由于某些原因导致对象无法回收,仍然占用着内存,这就是内存泄漏. 为什么会产生内存泄漏,内存泄漏会导致什么问题? 相比C++需要手动去 ...

最新文章

  1. FootSwitch脚踏开关:三位USB静音脚踏板脚踏开关脚踏键盘鼠标
  2. nodejs 中on 和 emit
  3. ubuntu安装http server
  4. 将WebApiTestClient添加到ASP.NET Web API帮助页面
  5. linux文件系统 tty who 环境变量 获取帮助
  6. PyTorch更新了:支持Windows,新增零维张量
  7. oracle-01122,oracle ORA-01200ORA-01110ORA-01122
  8. 高通:蓝牙5.0将可同时连接两个设备
  9. matlab中的tall,tall 数组 - MATLAB Simulink - MathWorks 中国
  10. netlink 0001 --- 基础简介
  11. 字节跳动java一共几面_字节跳动Java面经(已offer)
  12. AD域权限分配_ADManager Plus对AD域管理有哪些帮助作用?
  13. 一场对爱情的反思《少有人走的路:心智成熟的旅程》
  14. 好看的原创弹窗公告代码分享
  15. 常用三角公式、变形及图形
  16. 中转网关 (Transit Gateway) Connect连接类型集成FortiGate安全服务
  17. ZY Player 2.8.3 中文版 (全网视频播放器)
  18. 2018-2019赛季的前一半
  19. Rust 引入其他的 rs 文件
  20. 想做跨境电商,这几种收款方式必须知道!!

热门文章

  1. Sql优化之Mysql表分区
  2. 我的2017:从工作再到学生
  3. asp.net 页面缓存、数据缓存
  4. centos 6.x下jira显示饼图乱码解决方法
  5. Linux php.ini设置date.timezone=XXX为什么不生效?
  6. 标准BST二叉搜索树写法
  7. hdu 4536 dfs
  8. 欧盛K7儿童手机,全面保护青少年儿童身心健康
  9. Oracle_PL/SQL(3) 游标
  10. c# DateTime常用用法