内存泄漏检查

上传人:壹****1 文档编号:507472508 上传时间:2023-05-31 格式:DOCX 页数:19 大小:651.51KB
返回 下载 相关 举报
内存泄漏检查_第1页
第1页 / 共19页
内存泄漏检查_第2页
第2页 / 共19页
内存泄漏检查_第3页
第3页 / 共19页
内存泄漏检查_第4页
第4页 / 共19页
内存泄漏检查_第5页
第5页 / 共19页
点击查看更多>>
资源描述

《内存泄漏检查》由会员分享,可在线阅读,更多相关《内存泄漏检查(19页珍藏版)》请在金锄头文库上搜索。

1、内存泄漏检测方法 对于不同的程序可以使用不同的方法来进行内存泄漏的检查,还可以使用一些专门 的工具来进行内存问题的检查,例如 MemProof、AQTime、Purify、BundsChecker 等。 也可以使用简单的办法:利用 Windows 自带的 Perfmon 来监控程序进程的 handle count、Virtual Bytes 和 Working Set 3 个计数器。Handle Count 记录了进程当前打开的句柄个数,监视这个计数器有助于发现程序是否存在句 柄类型的内存泄漏;Virtual Bytes记录了程序进程在虚拟地址空间上使用的虚拟内存的大小,Virtual Byt

2、es 一般 总大于程序的Working Set,监视Virtual Bytes可以帮助发现一些系统底层的问题;Working Set记录了操作系统为程序进程分配的内存总量,如果这个值不断地持续增加,而 Virtual Bytes 却跳跃式地增加,则很可能存在内存泄漏问题。堆栈内存泄漏 堆栈空间不足会导致在受托管的情况下引发StackOverflowException类型的异常,线 程泄漏是堆栈内存泄漏的其中一种。线程发生泄漏,从而使线程的整个堆栈发生泄 漏。 如果应用程序为了执行后台工作而创建了大量的工作线程,但却没有正常终止这些 线程,则可能会引起线程泄漏。一个堆栈内存泄漏的例子:priva

3、te 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检测线程堆栈泄漏 默认堆栈

4、大小为1MB,因此如果应用程序的Private Bytes不断增大,同时.NET CLR LocksAndThreads 中的 # of current logical Threads 也相应地增大,那么就很可能是 发生了线程堆栈泄漏。 可以利用 Perfmon 来判断是否存在内存泄漏现象。添加计数蛊r使用本地计算机计数器(L) 広从计算机选择计数器(M):|ll.ll.8F38C5H4FLiBE480性能对象辺:.NET CLE. Lnk:2ATL&Thrm:m&2 r所有计数器卩从列表选择计数器(T)ical Thr# of cm_rent physi c:al Thr】# of cote

5、nt rec0gni zed U# of t口t:J rec0gni zed thr* ContmrLtiorL Rmt己./ secCut-rent Queue Leng thLI11 an a T artb+h / c a c添抑 I说明r所有范例(A)卩从列表选择范例a):_Glob:il. deTenvMemoryLe:ikTe s 11M em orj-Le :akT 己 211. vsho s t关闭 I执行被测试程序的相关操作,并在性能监视器中密切注意“Private Bytes”和“# of current logical Threads两个计数器的变化曲线,如果Private

6、 Bytes不断增大,同时# of current logical Threads 也相应地增大,则可判断程序发生了线程堆栈泄漏。用 CLRProfiler 定位线程泄漏代码利用CLRProfiler可以帮助检查程序是否存在线程泄漏。方法如下:(1) 启动 CLRProfiler(2) 单击 “Start Application按钮(3) 选择需要测试的应用程序,单击“打开”按钮。CLRProfiler会自动打开被测试程序,执 行程序的相关操作,然后单击CLRProfiler的“Show Heap Now”按钮说明:这个界面显示了程序的所有堆分配的情况。其中可以看到线程类中分配了 82K,占了

7、 18%以上,其中包含1500个线程对象。(4) 选中 “Threading.Thread 的节点,单击右键,选择“Show Who Allocated 说明:在这个界面中可以看到是哪个类的哪个方法创建了这么多的线程对象,在这里可以看 到是由buttonl_Click方法调用了线程类,从而定位到引发线程泄漏的代码。资源泄漏 资源通常指系统的对象。例如GDI对象句柄、内存句柄等,在软件编程过程中,使 用到很多这些资源对象,但是没有及时地释放掉就造成了资源泄漏。GDI泄漏是指程序申请了 GDI句柄,但是没有及时释放,导致GDI句柄不断累积。 GDI泄漏可能导致系统不稳定,或者出现花屏。一个 GDI

8、 泄漏的例子 : Form1: / 调用 Form2 窗体Form2 f = new Form2();/ 显示 Form2 窗体f.ShowDialog(); Form2: private void Form2_Load(object sender, EventArgs e) / 使用 pictureBox 控件加载并显示一个图片pictureBox1.Image = Image.FromFile(picture.JPG);private void Form2_FormClosing(object sender, FormClosingEventArgs e) /如果少了这句,则会发生GDI资

9、源泄漏 /pictureBox1.Image.Dispose();用 Windows 任务管理器协助检测 GDI 泄漏对于上面的GDI泄漏代码,可以利用Windows的任务管理器来协助检测。方法如下: (1)首先打开 Windows 任务管理器(2) 选择菜单“查看丨选择列”,出现如图15.13所示界面。确保“GDI对象”被勾选上,然 后单击“确定”按钮。(3) 启动被测试程序ResourceLeak (即上面的代码例子的可执行程序),并在Windows任 务管理器中定位到被测试程序的进程(4) 记下应用程序进程的当前GDI对象数,然后运行程序的各项操作,在操作过程中密切 关注其GDI对象数的

10、变化,例如,对于ResourceLeak.exe进程,当前的GDI对象数是33, 如果点击button1,程序将调出第二个窗口,窗口加载了一个图片,这个过程会向系统申请 一些GDI对象资源,因此查看Windows任务管理器可以看到其GDI对象数的变化(5) 这时候,把第二个窗口关闭,如果程序存在资源泄漏,则GDI对象数不会减少到33。 而且反复操作程序,调出第二个窗口再关闭,可看到GDI对象数不断地增加,这样就可判 断程序存在GDI资源泄漏的现象。利用GdiUsage检查GDI泄漏GdiUsage是Christophe Nasarre写的一个专门用于检查程序使用GDI资源情况的小 工具它的使用

11、方法也很简单,具体使用方法如下:(1) 首先在上面的输入框输入需要测试的程序路径,然后按“Start”按钮启动被测试程序, 程序被启动的同时,GdiUsage会显示一个“Debuggee Output”窗口,用于展示程序加载的DLL 名称以及地址(2) 启动程序后,在GdiUsage中单击“Take Snapshots”按钮,给当前程序使用的GDI资源 情况取一个“快照”(3) 可看到当前程序使用到1个Bitmap类型的GDI对象,单击“Details”按钮,还可以看到 详细的资源展示界面(4) 接着操作被测试程序(单击ResouceLeark程序的buttonl按钮),再单击一下“Take

12、Snapshots按钮,给当前程序使用的GDI资源情况取一个“快照”(5) 可以看到当前程序使用的Bitmap对象增加到2 个, Region对象增加1个。这时关闭 ResouceLeark程序的Form2窗口,再取一个快照,则发现Bitmap对象和Region对象的个数 都未减少,并且如果重复这个过程, Bitmap 对象的个数会不断地增加。因此可以认为程序 存在资源泄漏的现象。GDI 与 GDI+1、概述GDI在全称是Graphics Device Interface,即图形设备接口。是图形显示与实际物理 设备之间的桥梁。GDI接口是基于函数,虽然使程序员省力不少,但是编程方式依然显得麻

13、烦。例如显示一张位图,我们需要进行“创建位图,读取位图文件信息,启用场景设备,调 色板变化“等一系列操作。然而有了GDI+,繁琐的步骤再次被简化。顾名思义,GDI+就是 GDI的增强版,它是微软在Windows 2000以后操作系统中提供的新接口。2、GDI+主要功能GDI+主要提供以下三种功能:(1)二维矢量图形:GDI+提供了存储图形基元自身信息的类(或结构体)、存储图形基元绘制方式信息的类以及实际进行绘制的类;(2) 图像处理:大多数图片都难以划定为直线和曲线的集合,无法使用二维矢量图 形方式进行处理。因此,GDI+为我们提供了 Bitmap、Image等类,它们可用于显示、操作和 保存

14、 BMP、 JPG、 GIF 等图像格式。(3) 文字显示:GDI+支持使用各种字体、字号和样式来显示文本。相比于GDI,GDI+是基于C+类的对象化的应用程序接口,因此用起来更为简单。GDI的核心 是设备上下文,GDI函数都依赖于设备上下文句柄,其编程方式是基于句柄的;GDI+无需 时刻依赖于句柄或设备上下文,用户只需创建一个 Graphics 对象,就可以用面向对象的方 式调用其成员函数进行图形操作,编程方式是基于对象的。3、GDI绘制实例GDI在使用设备上下文绘制线条之前,必须先调用SelectObject以使笔对象和设备上下文关 联。其后,在设备上下文中绘制的所有线条均使用该笔,直到选

15、择另一支不同的笔为止。 使用GDI画线代码如下/ TODO: Add your command handler code hereCClientDC clientDC; /目标 DCCPen pen (PS_SOLID, 1, RGB(0, 0, 255); clientDC.SelectObject(pen.GetSafeHandle();/开始绘制clientDC.MoveTo(0, 0)clientDC.LineTo(rect.right, 0); clientDC.SelectObject(oldObject);从上述代码可以看出:在GDI编程中,几乎所有的操作都围绕设备上下文dc展开。 的确,这正是GDI编程的特点!设备上下文是Windows使用的一种结构,所有GDI操作 前都需取得特定设备的上下文,函数中的CClientDC dc (this)语句完成这一功能。利用GDI 进行图形、图像处理的一般操作步骤为: 1. 取得指定窗口的 DC。 2. 确定使用的坐标系及 映射方式。3.进行图形、图像或文字处理。4.释放所使用的DC。但是,在GD

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 学术论文 > 其它学术论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号