内存泄漏检查.doc
文本预览下载声明
内存泄漏检测方法
对于不同的程序可以使用不同的方法来进行内存泄漏的检查,还可以使用一些专门的工具来进行内存问题的检查,例如MemProof、AQTime、Purify、BundsChecker等。
也可以使用简单的办法:利用Windows自带的Perfmon来监控程序进程的handle count、Virtual Bytes和Working Set 3个计数器。
Handle Count记录了进程当前打开的句柄个数,监视这个计数器有助于发现程序是否存在句柄类型的内存泄漏;
Virtual Bytes记录了程序进程在虚拟地址空间上使用的虚拟内存的大小,Virtual Bytes一般总大于程序的Working Set,监视Virtual Bytes可以帮助发现一些系统底层的问题;
Working Set记录了操作系统为程序进程分配的内存总量,如果这个值不断地持续增加,而Virtual Bytes却跳跃式地增加,则很可能存在内存泄漏问题。
堆栈内存泄漏
堆栈空间不足会导致在受托管的情况下引发StackOverflowException类型的异常,线程泄漏是堆栈内存泄漏的其中一种。线程发生泄漏,从而使线程的整个堆栈发生泄漏。
如果应用程序为了执行后台工作而创建了大量的工作线程,但却没有正常终止这些线程,则可能会引起线程泄漏。
一个堆栈内存泄漏的例子:
private void button1_Click(object sender, EventArgs e)
{
// 循环启动多个线程
for (int i = 0; i 1500; i++)
{
Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();
}
}
static void ThreadProc()
{
Console.WriteLine(启动 Thread #{0} ,Thread.CurrentThread.ManagedThreadId);
// 阻塞直到当前线程结束
Thread.CurrentThread.Join();
}
}
利用Perfmon检测线程堆栈泄漏
默认堆栈大小为1MB,因此如果应用程序的Private Bytes不断增大,同时.NET CLR LocksAndThreads中的 # of current logical Threads 也相应地增大,那么就很可能是发生了线程堆栈泄漏。
可以利用Perfmon来判断是否存在内存泄漏现象。
执行被测试程序的相关操作,并在性能监视器中密切注意“Private Bytes”和“# of current logical Threads”两个计数器的变化曲线,如果Private Bytes不断增大,同时# of current logical Threads 也相应地增大,则可判断程序发生了线程堆栈泄漏。
用CLRProfiler定位线程泄漏代码
利用CLRProfiler可以帮助检查程序是否存在线程泄漏。方法如下:
(1)启动CLRProfiler
(2)单击“Start Application”按钮
(3)选择需要测试的应用程序,单击“打开”按钮。CLRProfiler会自动打开被测试程序,执行程序的相关操作,然后单击CLRProfiler的“Show Heap Now”按钮
说明:这个界面显示了程序的所有堆分配的情况。其中可以看到线程类中分配了82K,占了18%以上,其中包含1500个线程对象。
(4)选中“Threading.Thread”的节点,单击右键,选择“Show Who Allocated”
说明:在这个界面中可以看到是哪个类的哪个方法创建了这么多的线程对象,在这里可以看到是由button1_Click方法调用了线程类,从而定位到引发线程泄漏的代码。
资源泄漏
资源通常指系统的对象。例如GDI对象句柄、内存句柄等,在软件编程过程中,使用到很多这些资源对象,但是没有及时地释放掉就造成了资源泄漏。
GDI泄漏是指程序申请了GDI句柄,但是没有及时释放,导致GDI句柄不断累积。GDI泄漏可能导致系统不稳定,或者出现花屏。
一个GDI泄漏的例子 :
Form1:
// 调用Form2窗体
Form2 f = new Form2();
// 显
显示全部