.NET中常见的内存泄漏和解决办法
在.NET中,虽然CLR的GC垃圾回收器帮我们自动回收托管堆对象,释放内存,最大程度避免了"内存泄漏"(应用程序所占用的内存没有得到及时释放),但.NET应用程序"内存泄漏"的问题还是会存在,如果不加以注意,"内存泄漏"时有发生。
有关流以及Reader或Writer引起的内存泄漏
比如,把文件读取到流中:
public static string ReadFile(){var filePath = @"硬盘地址";var sr = new StreamReader(filePath);return sr.ReadToEnd();}
以上,StreamReader在读取数据后没有解释销毁,存在"内存泄漏"。正确的做法是在使用完后及时关闭。
public static string ReadFile(){var filePath = @"硬盘地址";using(var sr = new StreamReader(filePath)){return sr.ReadToEnd();}}
或者
public static string ReadFile(){var filePath = @"硬盘地址";var sr = new StreamReader(filePath);var result = sr.ReadToEnd();sr.Close();return result;}
以上,需要我们注意的是:当通过某种流的构造函数创建的对象实例,注意及时关闭。
有时候,通过某个方法返回某种流的对象实例,也会忘记关闭。比如以下:
//创建字节数组var data = new byte[1024];var client = new TcpClient();//从TCP实例方法返回流var stream = client.GetStream();//把流读到字节数组中int bytesLength = stream.Read(data, 0, data.Length);//字节数组转换城字符串var result = System.Text.Encoding.ASCII.GetString(data, 0, bytesLength);
正确的写法应该是:
//创建字节数组var data = new byte[1024];var client = new TcpClient();//从TCP实例方法返回流var stream = client.GetStream();//把流读到字节数组中int bytesLength = stream.Read(data, 0, data.Length);stream.Close();//字节数组转换城字符串var result = System.Text.Encoding.ASCII.GetString(data, 0, bytesLength);
同理,其它与流有关的类,我们也需要注意在用完后及时关闭:
● FileStream
● MemoryStream
● StreamReader
● TextWriter
......
静态引用引起的内存泄漏
对于静态实例来说,除非应用程序关闭,对应的内存一直得不到释放。比如有如下遵循"Siingleton"模式的类(没考虑线程安全)。
public class MySingletonClass{private static MySingletonClass myInstance;private static List<IAmBig> bigObjects = new List<IAmBig>();private MySingletonClass(){}public static MySingletonClass MyInstance{get{if(myInstance == null){myInstance = new MySingletonClass();}return myInstance;}}public static IAmBig CreateBigObject(){var bigObject = new IAmBig();bigobject.AllocateMemory(4096);bigObjects.add(bigObject);return bigObject;}}public class IAmBig{}
以上,每次调用CreateBigObject静态方法,都往List<IAmBig>类型集合中添加,由于MySingletonClass静态类实例一直存在于应用程序的生命周期,再加上GC不会释放bigObjects这个集合对象实例,于是就出现了"内存泄漏"。解决办法是避免让静态实例引用其它实例对象,避免出现静态实例的链式引用。
委托引起的内存泄漏
比如有2个委托形成的委托链。
var objectOne = new ObjectOne();var objectTwo = new ObjectTwo();objectOne.StateChanged += objectTwo.StateChangedEventHandler;objectTwo.Dispose();
以上,把objectTwo的委托注册给了objectOne,这样objectOne和objectTwo有依赖关系,形成了依赖链。只有当objectOne被释放,才能释放objectTwo。如果objectOne恰巧是全局静态实例,那在应用程序的生命周期内,objectTwo一直得不到内存释放,造成了"内存泄漏"。
解决办法是在调用objectTwo的Dispose方法之前,先解开两者的依赖关系。修改如下:
var objectOne = new ObjectOne();var objectTwo = new ObjectTwo();objectOne.StateChanged += objectTwo.StateChangedEventHandler;......objectOne.StateChanged -= objectTwo.StateChangedEventHandler;objectTwo.Dispose();
非托管资源引起的内存泄漏
public class MyUnManagedExample{public void Allocate(){IntPtr pointer = Marshal.AllocHGlobal(1024);}}
对于创建的非托管类型的实例ponter,需要显式释放。
Marshal.FreeGlobal(pointer);
实现IDisposable接口的类引起的内存泄漏
所有实现IDisposable接口的类都有一个Dispose方法,如果忘记调用,就造成"内存泄漏"。
.NET中常见的内存泄漏和解决办法的更多相关文章
- android中常见的内存泄漏和解决的方法
android中的内存溢出预计大多数人在写代码的时候都出现过,事实上突然认为工作一年和工作三年的差别是什么呢.事实上干的工作或许都一样,产品汪看到的结果也都一样,那差别就是速度和质量了. 写在前面的一 ...
- Android开发常见的Activity中内存泄漏及解决办法
上一篇文章楼主提到由Context引发的内存泄漏,在这一篇文章里,我们来谈谈Android开发中常见的Activity内存泄漏及解决办法.本文将会以“为什么”“怎么解决”的方式来介绍这几种内存泄漏. ...
- Android中常见的内存泄漏
为什么会产生内存泄漏? 当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏. ...
- Android性能优化之利用LeakCanary检测内存泄漏及解决办法
前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...
- Js中常见的内存泄漏场景
常见的内存泄漏场景 内存泄漏Memory Leak是指程序中已动态分配的堆内存由于疏忽或错误等原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果.内存泄漏并非指内 ...
- AFNetworking 3.0中调用[AFHTTPSessionManager manager]方法导致内存泄漏的解决办法
在使用AFNetworking3.0框架,使用Instruments检查Leaks时,检测到1000多个内存泄漏的地方,定位到 [AFHTTPSessionManager manager] 语句中,几 ...
- Swift代理造成内存泄漏的解决办法
在swift中,使用代理 ,可能很多人会这样实现: .首先定义一份协议. protocol ToolProrocol{ //代理方法 func didRecieveResults(result:Int ...
- JS 调试中常见的报错的解决办法
报错:Uncaught SyntaxError: Unexpected token o in JSON at position 1 at JSON.parse (<anonymous>) ...
- css中常见margin塌陷问题之解决办法
塌陷问题 当两个盒子在垂直方向上设置margin值时,会出现一个有趣的塌陷现象. ①垂直并列 首先设置两个DIV,并为其制定宽高 1 /*HTML部分*/ 2 <body> 3 <d ...
随机推荐
- svn 回退/更新/取消至某个版本命令详解【转】
转自:http://www.cnblogs.com/mfryf/p/4654110.html 1. 取消Add/Delete 取消文件 svn revert 文件名 取消目录 svn revert - ...
- PHP中冒号、endif、endwhile、endfor使用介绍
我们经常在wordpress一类博客程序的模板里面看到很多奇怪的PHP语法,比如: 复制代码代码如下: <?php if(empty($GET_['a'])): ?> <font c ...
- win7下PHP+MySQL+CoreSeek中文检索引擎配置
1.Windows下的coreseek安装测试 (64位win7旗舰版) 官方参考:http://www.coreseek.cn/products-install/install_on_windows ...
- LCT摘要
介绍.用途 LCT是树链剖分中的一种,又叫实链剖分.动态树,常用于维护动态的树.森林. 维护方式 LCT并不直接维护原树,而是用一堆splay作为辅助树来维护.原树中的一条实链上的点在一棵splay中 ...
- jexus http to https
一.摘要 1.80端口上只要没有网站使用 hosts=* 这样的配置,jexus会自动将域名跳转到 https 上.也就是说,你把网站默认配置文件default中的hosts=*改成具体的其它的域名, ...
- TcxGrid 标题头高度
- 使用jstl方式替换服务器请求地址
<c:set var="ctx" value="${pageContext.request.contextPath}"></c:set>
- 索引Hint提示(INDEX Hint)
定义:所谓的索引Hint提示,就是强制查询优化器为一个查询语句执行扫描或者使用一个指定的索引 前提:利用索引提示的前提就是当前表存在索引了,如果是堆表的情况,只能通过表扫描获取数据了. 用处:很多时候 ...
- 定制自己的new和delete:operator new 和 operator delete
new和delete不同用法 基本用法 int * aptr = new int(10); delete aptr, aptr = nullptr; 上面的代码是我们最基本也是最常见的使用new和de ...
- Codeforces Round #257 (Div. 1) D - Jzzhu and Numbers 容斥原理 + SOS dp
D - Jzzhu and Numbers 这个容斥没想出来... 我好菜啊.. f[ S ] 表示若干个数 & 的值 & S == S得 方案数, 然后用这个去容斥. 求f[ S ] ...