.NET 程序内存泄漏排查的两种方式

概述

.NET中托管内存在使用完毕后会在合适的时机被垃圾回收,非托管的内存则不会被自动回收,如果这些非托管的资源没有释放或者及时释放,程序长时间运行会导致内存慢慢被占满直到程序崩溃.

.NET中常见的内存泄漏主要有以下三种:.

1、静态变量泄露

静态变量中的成员所占用的内存如果不手动处理是无法自动释放的,如单例模式;

2、非托管资源泄露:非托管资源不会自动回收,使用完成后需要手动释放,一般是通过实现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");
        }
    }
}

3、事件委托导致资源泄露:这种一般使用完成记得解订阅就可以.

内存泄露排查方法

方式1:通过VS附加进程debug方式第一步:调试-》窗口-》显示诊断工具:

.NET 程序内存泄漏排查的两种方式

第二步:选择内存使用率-》截取快照,前后截图两次快照

.NET 程序内存泄漏排查的两种方式
.NET 程序内存泄漏排查的两种方式

第三步:分析增长的内存,双击垫块堆大小后增长的红色箭头:这里可以看到内存增长的数据类型:

.NET 程序内存泄漏排查的两种方式
.NET 程序内存泄漏排查的两种方式

方式2:通过第三方的工具:.NET Memory Profiler,下载后按照默认安装方式安装,安装好后打开有6天的试用期,可以修改下注册表延长时限:

.NET 程序内存泄漏排查的两种方式
.NET 程序内存泄漏排查的两种方式

注册好以后可以先附加进程,然后也是捕获两次内存快照,

.NET 程序内存泄漏排查的两种方式
.NET 程序内存泄漏排查的两种方式

然后通过快速增长的那部分村内去分析具体没有释放的类!