.NET中托管内存在使用完毕后会在合适的时机被垃圾回收,非托管的内存则不会被自动回收,如果这些非托管的资源没有释放或者及时释放,程序长时间运行会导致内存慢慢被占满直到程序崩溃.
.NET中常见的内存泄漏主要有以下三种:
静态变量泄露: 静态变量中的成员所占用的内存如果不手动处理是无法自动释放的,如单例模式;
非托管资源泄露:非托管资源不会自动回收,使用完成后需要手动释放,一般是通过实现dispose仿作实现释放,dispose一般写法如下: public class SampleClass : IDisposable { //演示创建一个非托管资源 private IntPtr nativeResource = Marshal.AllocHGlobal( 100 ); //演示创建一个托管资源 private Test test = new Test; private bool disposed = false ; /// <summary> /// 实现IDisposable中的Dispose方法 /// </summary> public void Dispose ( ) { //必须为true Dispose( true ); //通知垃圾回收机制不再调用终结器(析构器) GC.SuppressFinalize( this ); } /// <summary> /// 不是必要的,提供一个Close方法仅仅是为了更符合其他语言(如C++)的规范 /// </summary> public void Close ( ) { Dispose; } /// <summary> /// 必须,以备程序员忘记了显式调用Dispose方法 /// </summary> ~SampleClass { //必须为false Dispose( false ); } /// <summary> /// 非密封类修饰用protected virtual /// 密封类修饰用private /// </summary> /// <param name="disposing"> </param> protected virtual void Dispose ( bool disposing ) { if (disposed) { return ; } if (disposing) { // 清理托管资源 if (test != null ) { test.Dispose; test = null ; } } // 清理非托管资源 if (nativeResource != IntPtr.Zero) { Marshal.FreeHGlobal(nativeResource); nativeResource = IntPtr.Zero; } //让类型知道自己已经被释放 disposed = true ; } public void SamplePublicMethod ( ) { if (disposed) { throw new ObjectDisposedException( "SampleClass" , "SampleClass is disposed" ); } } }
内存泄露排查方法
方式1:通过vs附加进程debug方式
第一步:调试-》窗口-》显示诊断工具:
第二步:选择内存使用率-》截取快照,前后截图两次快照
第三步:分析增长的内存,双击垫块堆大小后增长的红色箭头:这里可以看到内存增长的数据类型:
方式2:
通过第三方的工具:.NET Memory Profiler,下载后按照默认安装方式安装,安装好后打开有6天的试用期,可以修改下注册表延长时限:
注册好以后可以先附加进程,然后也是捕获两次内存快照,
然后通过快速增长的那部分村内去分析具体没有释放的类!
公众号:dotnet讲堂
返回搜狐,查看更多
责任编辑:
声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
发布于:
山西省