.NET 常见内存泄漏

简介

以前认为,.NET程序内存都是托管的,如果不是调用非托管资源,应该不会存在内存泄漏的问题,但是,最近两天对归档程序内存使用分析,发现,事情不是想象的那么简单。

 

.NET内存泄漏,更准确的说应该是对象超过生命周期而不能被GC回收。本文列举了几种可能导致内存泄漏的情形,并提供示例代码,及解决方案,希望对大家有所帮助。

 

所举的例子都是经过自己极端简化过的,只是为了说明观点,具体项目中遇到的情形会复杂很多,需要具体分析。

事件注册后未解除注册

示例代码

程序运行时,内存使用情况如图:

原因分析

示例代码中,表面看起来,一次循环过后,上次new出来的对象a,不会继续被引用到,应该被视为垃圾,下次垃圾回收的时候,会被回收掉。但是,通过实验证明,对象a是不会被回收掉的。

 

原因是因为,对象b注册了click事件而未销毁,导致对象b会一直引用到a,a不会被视为垃圾被GC回收。

解决办法

对象a生命周期结束后,解除事件的注册,只有这样,a所占用的内存才会在下次垃圾回收的时候被回收掉。

下图为解除事件注册绑定后,内存的使用情况:

静态引用

示例代码

如果一直调用CreateObject方法,程序运行时,内存使用情况如图:

原因分析

静态变量的生命周期是全局的,即程序不退出,所占用的内存一直不会被释放掉。

解决办法

尽量少用静态成员,若一定要使用,注意静态成员引用的对象是否会一直增长。

控件不使用后未销毁

示例代码

程序运行时,内存使用情况如图:

原因分析

示例代码中,控件lbl已经被移除了,表面看起来,下次循环时,该控件应该被视为垃圾,在下次垃圾回收时,被回收掉。但实验证明,内存不会被回收掉。原因在于,控件未被真正销毁掉。

解决办法

控件生命周期结束之后,调用Dispose方法,确保控件能被真正销毁掉。

下图为调用Dispose方法后,内存的使用情况:

 

调用非托管资源而未释放

示例代码

原因分析

使用未托管对象之后忘记释放。

解决办法

对于实现了IDisposable接口的类可以使用using方式使用,或者显示调用Dispose方法。

工具

日志输出

穷人的工具,输出进程内存使用量 :)

任务管理器

通过观察任务管理器内存使用情况,查看是否存在内存泄露。

 

.NET Memory Profiler

专业的.NET性能调优工具,缺点,不是免费的 :)

参考

 

转载于:https://www.cnblogs.com/wwlzz/p/4318294.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值