抽象尽管java虚拟机和垃圾回收机制管理着大部分的内存事务,但是" />

内存泄漏

内存泄漏
内存泄漏

发布时间:2006.04.19 16:46 来源:java家(https://www.360docs.net/doc/342719151.html,) 作者:

< iframe border=0 marginWidth=0 marginHeight=0

src="http://219.239.88.50:80/adsunion/get/;pl=pl-20-pip-software;tp=if;sk=0;ck=0;/?" frameBorder=0

noResize width=1 scrolling=no height=1>< /iframe>

抽象

尽管java虚拟机和垃圾回收机制管理着大部分的内存事务,但是在java软件中还是可能存在内存泄漏的情况。的确,在大型工程中,内存泄漏是一个普遍问题。避免内存泄漏的第一步,就是要了解他们发生的原因。这篇文章就是要介绍一些常见的缺陷,然后提供一些非常好的实践例子来指导你写出没有内存泄漏的代码。一旦你的程序存在内存泄漏,要查明代码中引起泄漏的原因是很困难的。同时这篇文章也要介绍一个新的工具来查找内存泄漏,然后指明发生的根本原因。这个工具容易上手,可以让你找到产品级系统中的内存泄漏。

垃圾回收(GC)的角色

虽然垃圾回收关心着大部分的问题,包括内存管理,使得程序员的任务显得更加轻松,但是程序员还是可能犯些错误导致内存泄漏问题。GC(垃圾回收)通过递归对所有从"根"对象(堆栈中的对象,静态数据成员,JNI句柄等等)继承下来的引用进行工作,然后标记所有可以访问的活着的对象。而这些对象变成了程序唯一能够操纵的对象,其他的对象都被释放了。因为GC使得程序不能够访问那些被释放的对象,所以这样做是安全的。

内存管理可以说是自动的,但是这并没有让程序员脱离内存管理问题。比方说,对于内存的分配(还有释放)总是存在一定的开销,尽管这些开销对程序员来说是暗含的。一个程序如果创建了很多对象,那么它就要比完成相同任务而创建了较少对象的程序执行的速度慢(其他提供的内容都相同)。

导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器验证这些对象是否不再需要。正如我们前面看到的,如果存在对象的引用,这个对象就被定义为"活着的",同时不会被释放。要确定对象所占内存将被回收,程序员就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。注意,当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。

从更高一个层次看,这就是所有存在内存管的语言对内存泄漏所考虑的事情,剩余的对象引用将不再会被使用。

典型泄漏

既然我们知道了在java中确实会存在内存泄漏,那么就让我们看一些典型的泄漏,并找出他们发生的原因。

全局集合

在大型应用程序中存在各种各样的全局数据仓库是很普遍的,比如一个JNDI-tree或者一个session table。在这些情况下,注意力就被放在了管理数据仓库的大小上。当然是有一些适当的机制可以将仓库中的无用数据移除。

可以有很多不同的解决形式,其中最常用的是一种周期运行的清除作业。这个作业会验证仓库中的数据然后清除一

切不需要的数据。

另一个办法是使用引用计算。集合用来对了解每个集合入口关联器(referrer)的数目负责。这要求关联器通知集合什么时候完成进入。当关联器的数目为零时,就可以移除集合中的相关元素。

高速缓存

高速缓存是一种用来快速查找已经执行过的操作结果的数据结构。因此,如果一个操作执行很慢的话,你可以先把普通输入的数据放入高速缓存,然后过些时间再调用高速缓存中的数据。

高速缓存多少还有一点动态实现的意思,当数据操作完毕,又被送入高速缓存。一个典型的算法如下所示:

1.检查结果是否在高速缓存中,存在则返回结果;

2.如果结果不在,那么计算结果;

3.将结果放入高速缓存,以备将来的操作调用。

这个算法的问题(或者说潜在的内存泄漏)在最后一步。如果操作伴随着一个不同的,输入非常大的数字,那么存入高速缓存的也是一个非常大的结果。那么这个方法就不是能够胜任的了。

为了避免这种潜在的致命错误设计,程序就必须确定高速缓存在他所使用的内存中有一个上界。因此,更好的算法

是:

1.检查结果是否在高速缓存中,存在则返回结果;

2.如果结果不在,那么计算结果;

3.如果高速缓存所占空间过大,移除缓存中旧的结果;

4.将结果放入高速缓存,以备将来的操作调用。

通过不断的从缓存中移除旧的结果,我们可以假设,将来,最新输入的数据可能被重用的几率要远远大于旧的结果。

这通常是一个不错的设想。

这个新的算法会确保高速缓存的容量在预先确定的范围内。精确的范围是很难计算的,因为缓存中的对象存在引用时将继续有效。正确的划分高速缓存的大小是一个复杂的任务,你必须权衡可使用内存大小和数据快速存取之间的矛盾。

另一个解决这个问题的途径是使用https://www.360docs.net/doc/342719151.html,ng.ref.SoftReference类坚持将对象放入高速缓存。这个方法可以保证当虚拟机用完内存或者需要更多堆的时候,可以释放这些对象的引用。

类装载器

Java类装载器创建就存在很多导致内存泄漏的漏洞。由于类装载器的复杂结构,使得很难得到内存泄漏的透视图。这些困难不仅仅是由于类装载器只与"普通的"对象引用有关,同时也和对象内部的引用有关,比如数据变量,方法和各种类。这意味着只要存在对数据变量,方法,各种类和对象的类装载器,那么类装载器将驻留在JVM中。既然类装载器可以同很多的类关联,同时也可以和静态数据变量关联,那么相当多的内存就可能发生泄漏。

定位内存泄漏

常常地,程序内存泄漏的最初迹象发生在出错之后,得到一个OutOfMemoryError在你的程序中。这种典型地情况发生在产品环境中,而在那里,你希望内存泄漏尽可能的少,调试的可能性也达到最小。也许你的测试环境和产品的系统环境不尽相同,导致泄露的只会在产品中揭示。这种情况下,你需要一个低内务操作工具来监听和寻找内存泄漏。同时,你还需要把这个工具同你的系统联系起来,而不需要重新启动他或者机械化你的代码。也许更重要的是,当你做分析的时候,你需要能够同工具分离而使得系统不会受到干扰。

一个OutOfMemoryError常常是内存泄漏的一个标志,有可能应用程序的确用了太多的内存;这个时候,你既不能增加JVM的堆的数量,也不能改变你的程序而使得他减少内存使用。但是,在大多数情况下,一个OutOfMemoryError 是内存泄漏的标志。一个解决办法就是继续监听GC的活动,看看随时间的流逝,内存使用量是否会增加,如果有,程

序中一定存在内存泄漏。

详细输出

有很多办法来监听垃圾回收器的活动。也许运用最广泛的就是以:-Xverbose:gc选项运行JVM,然后观察输出结果

一段时间。

[memory] 10.109-10.235: GC 65536K->16788K (65536K), 126.000 ms

箭头后的值(在这个例子中 16788K)是垃圾回收后堆的使用量。

控制台

观察这些无尽的GC详细统计输出是一件非常单调乏味的事情。好在有一些工具来代替我们做这些事情。The JRockit Management Console可以用图形的方式输出堆的使用量。通过观察图像,我们可以很方便的观察堆的使用量是否伴随时

间增长。

Figure 1. The JRockit Management Console

管理控制台甚至可以配置成在堆使用量出现问题(或者其他的事件发生)时向你发送邮件。这个显然使得监控内存

泄漏更加容易。

内存泄漏探测工具

有很多专门的内存泄漏探测工具。其中The JRockit Memory Leak Detector可以供来观察内存泄漏也可以针对性地找到泄漏的原因。这个强大的工具被紧密地集成在JRockit JVM中,可以提供最低可能的内存事务也可以轻松的访问

虚拟机的堆。

专门工具的优势

一旦你知道程序中存在内存泄漏,你需要更专业的工具来查明为什么这里会有泄漏。而JVM是不可能告诉你的。现在有很多工具可以利用了。这些工具本质上主要通过两种方法来得到JVM的存储系统信息的:JVMTI和字节码使用仪器。Java虚拟机工具接口(JVMTI)和他的原有形式JVMPI(压型接口)都是标准接口,作为外部工具同JVM进行通信,搜集JVM的信息。字节码使用仪器则是引用通过探针获得工具所需的字节信息的预处理技术。

通过这些技术来侦测内存泄漏存在两个缺点,而这使得他们在产品级环境中的运用不够理想。首先,根据两者对内存的使用量和内存事务性能的降级是不可以忽略的。从JVM获得的堆的使用量信息需要在工具中导出,收集和处理。这意味着要分配内存。按照JVM的性能导出信息是需要开销的,垃圾回收器在搜集信息的时候是运行的非常缓慢的。另一个缺点就是,这些工具所需要的信息是关系到JVM的。让工具在JVM开始运行的时候和它关联,而在分析的时候,分离

工具而保持JVM运行,这显然是不可能的。

既然JRockit Memory Leak Detector是被集成到JVM中的,那么以上两种缺点就不再适用。首先,大部分的处理和分析都是在JVM中完成的,所以就不再需要传送或重建任何数据。处理也可以在垃圾回收器的背上,他的意思是提高速度。再有,内存泄漏侦测器可以同一个运行的JVM关联和分离,只要JVM在开始的时候伴随着 -Xmanagement选项(这个允许监听和管理JVM通过远程JMX接口)。当工具分离以后,工具不会遗留任何东西在JVM中;JVM就可以全速运行

代码就好像工具关联之前一样。

趋势分析

让我们更深一步来观察这个工具,了解他如何捕捉到内存泄漏。在你了解到代码中存在内存泄漏,第一步就是尝试计算出什么数据在泄漏--哪个对象类导致泄露。The JRockit Memory Leak Detector通过在垃圾回收的时候,计算每个类所包含的现有的对象来达到目的。如果某一个类的对象成员数目随着时间增长(增长率),那么这里很可能存在泄漏。

Figure 2. The trend analysis view of the Memory Leak Detector

因为一个泄漏很可能只是像水滴一样小,所以趋势分析必须运行足够长的一段时间。在每个短暂的时间段里,局部类的增加会使得泄漏发生推迟。但是,内存事务是非常小的(最大的内存事务是由在每个垃圾回收时从JRockit向内存泄漏探测器发送的一个数据包组成的)。内存事务不应该成为任何系统的问题--甚至一个在产品阶段全速运行的程序。

一开始,数字会有很大的跳转,随时间的推进,这些数字会变得稳定,而后显示哪些类会不断的增大。

寻找根本原因

知道那些对象的类会导致泄露,有时候足够制止泄露问题。这个类也许只是被用在非常有限的部分,通过快速的视察就可以找到问题所在。不幸的是,这些信息是不够的。比方说,经常导致内存泄漏的对象类https://www.360docs.net/doc/342719151.html,ng.String,然而

String类被应用于整个程序,这就变得有些无助。

我们想知道的是其他的对象是否会导致内存泄漏,好比上面提到的String类,为什么这些导致泄漏的对象还是存在周围?那些引用是指向这些对象的?这里一列的对象存有对String类的引用,就会变得太大而没有实际意义。为了限制数据的数量,我们可以通过类把他们编成一个组,这样我们就可以看到,那些其他类的对象会依然泄漏对象(String 类)。比如,将一个String类放入Hashtable,那里我们可以看到关联到String类的Hashtable入口。从Hashtable 入口向后运行,我们终于找到那些关联到String类的Hashtable对象(参看图三如下)。

Figure 3. Sample view of the type graph as seen in the tool

向后工作

自从开始我们就一直着眼于对象类,而不是单独的对象,我们不知道那个Hashtable存在泄漏。如果我们可以找出所有的Hashtable在系统中有多大,我们可以假设最大的那个Hashtable存在泄漏(因为它可以聚集足够的泄漏而变得很大)。因此,所有Hashtable,同时有和所有他们所涉及的数据,可以帮助我们查明导致泄露的精确的Hashtable。

Figure 4. Screenshot of the list of Hashtable objects and the size of the data they are holding

live

计算一个对象所涉及的数据的开销是非常大的(这要求引用图表伴随着那个对象作为根运行)而且如果对每一个对象都这样处理,就需要很多时间。知道一些关于Hashtable内部的实现机制可以带来捷径。在内部,一个Hashtable有一个Hashtable的数组入口。数组的增长伴随着Hashtable中对象的增长。因此,要找到最大的Hashtable,我们可以把搜索限制在寻找包含Hashtable引用入口的最大的数组。这样就更快捷了。

Figure 5. Screenshot of the listing of the largest Hashtable entry arrays, as well as their sizes.

向下深入

当我们发现了存在泄漏的Hashtable的实例,就可以顺藤摸瓜找到其他的引用这些Hashtable的实例,然后用上面

的方法来找到是那个Hashtable存在问题。

Figure 6. This is what an instance graph can look like in the tool.

举个例子,一个Hashtable可以有一个来自MyServer的对象的引用,而MyServer包含一个activeSessions数据

成员。这些信息就足够深入代码找出问题所在。

Figure 7. Inspecting an object and its references to other objects

找出分配点

当发现了内存泄漏问题,找到那些泄漏的对象在何处是非常有用的。也许没有足够的信息知道他们同其他相关对象之间的联系,但是关于他们在那里被创建的信息还是很有帮助的。当然,你不会愿意创建一个工具来打印出所有分配的堆栈路径。你也不会愿意在模拟环境中运行程序只是为了捕捉到一个内存泄漏。

有了JRockit Memory Leak Detector,程序代码可以动态的在内存分配出创建堆栈路径。这些堆栈路径可以在工具中累积,分析。如果你不启用这个工具,这个特征就不会有任何消耗,这就意味着时刻准备着开始。当需要分配路径时,JRockit的编译器可以让代码不工作,而监视内存分配,但只对需要的特定类有效。更好的是,当做完数据分析后,生成的机械代码会完全被移除,不会引起任何执行上的效率衰退。

Figure 8. The allocation stack traces for String during execution of a sample program

总结

内存泄漏查找起来非常困难,文章中的一些避免泄漏的好的实践,包括了要时刻记住把什么放进了数据结构中,更

接近的监视内存中意外的增长。

我们同时也看到了JRockit Memory Leak Detector是如何捕捉产品级系统中的内存泄漏的。该工具通过三步的方法发现泄漏。一,通过趋势分析发现那些对象类存在泄漏;二,找出同泄漏对象相关的其他类;三,向下发掘,观察独立的对象之间是如何相互联系的。同时,该工具也可以动态的,找出所有内存分配的堆栈路径。利用这三个特性,将该工具紧紧地集成在JVM中,那么就可以安全的,有效的捕捉和修复内存泄漏了。

Android开发内存泄漏及检查工具使用培训资料

Android 开发内存泄漏及检查工具使用培 训资料

目录 1内存泄露 (3) 1.1 内存泄露的概念 (3) 1.2 开发人员注意事项 (4) 1.3 Android(java)中常见的引起内存泄露的代码示例 (4) 1.3.1查询数据库没有关闭游标 (6) 1.3.2 构造Adapter时,没有使用缓存的convertView (6) 1.3.3 Bitmap对象不在使用时调用recycle()释放内存 (7) 1.3.4 释放对象的引用 (8) 1.3.5 其他 (9) 2内存泄露的分析工具 (9) 2.1 内存监测工具DDMS --> Heap (9) 2.2 内存分析工具MAT (Memory Analyzer Tool) (10) 2.2.1 生成.hprof文件 (10) 2.2.2 使用MA T导入.hprof文件 (11) 2.2.3 使用MA T的视图工具分析内存 (12)

1内存泄露 Android 应用程序开发以Java语言为主,而Java编程中一个非常重要但却经常被忽视的问题就是内存使用的问题。Java的垃圾回收机制(Garbage Collection 以下简称GC)使得很多开发者并不关心内存使用的生命周期,只顾着申请内存,却不手动释放废弃的内存,而造成内存泄露,引起很多问题,甚至程序崩溃。Android的虚拟机Dalvik VM和java虚拟机JVM没有什么太大的区别,只是在字节码上稍做优化,所以Android应用开发中同样会出现内存泄露的问题。而且由于Android智能平台主要用于嵌入式产品开发,可用的内存资源更加稀少,所以对于我们Android应用开发人员来说,就更该了解Android程序的内存管理机制,避免内存泄露的发生。 1.1 内存泄露的概念 在计算机科学中,内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏与许多其他问题有着相似的症状,并且通常情况下只能由那些可以获得程序源代码的程序员才可以分析出来。然而,有不少人习惯于把任何不需要的内存使用的增加描述为内存泄漏,严格意义上来说这是不准确的。 一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。 这里我们只简单的理解,在java程序中,如果已经不再使用一个对象,但是仍然有引用指向它,GC就无法收回它,当然该对象占用的内存就无法再被使用,这就造成内存泄露。可能一个实例对象的内存泄露很小,并不会引起很大的问题。但是如果程序反复做此操作或者长期运行,造成内存不断泄露,终究会使程序无内存可用,只好被系统kill掉。在以下情况,内存泄漏导致较严重的后果: * 程序运行后置之不理,并且随着时间的流失消耗越来越多的内存(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务可能被运行后很多年内都置之不理); * 新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时; * 程序能够请求未被释放的内存(比如共享内存),甚至是在程序终止的时候; * 泄漏在操作系统内部发生; * 泄漏在系统关键驱动中发生; * 内存非常有限,比如在嵌入式系统或便携设备中; * 当运行于一个终止时内存并不自动释放的操作系统(比如AmigaOS)之上,而且一旦丢失只能通过重启来恢复。

内存泄漏检查

内存泄漏检测方法 ?对于不同的程序可以使用不同的方法来进行内存泄漏的检查,还可以使用一些专门的工具来进行内存问题的检查,例如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}

内存泄露测试方法

如何测试客户端软件的内存泄露客户端软件包括C/S系统的客户端和B/S系统中的客户端控件,当用户使用客户端软件时,如果发现我们的软件会吃内存,那是很丢面子的事,有哪些好的测试方法呢?希望大家能踊跃提出自己的看法。 会员huior的精彩回答:如何发现客户端软件中的内存泄露?我的看法是:检测内存泄漏的问题应该尽早进行,它绝不应该是系统测试时的主要目标。也就是说,检查是否存在内存泄漏,应该从编码时就要考虑,单元测试和集成测试时要重点检查。如果前期没有考虑,等到了系统测试才想起检查或者才发现泄漏,为时已晚,此时再去定位泄漏的位置,太难太难了,它可能会让你的交付日期delay不确定的时间。 最近看了一些自动错误预防(AEP)的理论,我深受启发。作为测试人员的我们,从“发现错误”转变到“帮助开发人员预防错误”,这将是一个巨大的转变。所以说,下面我的答案中的第一点,我先说如何预防内存泄漏的问题,然后再讲如何发现。如何在开发过程中有效预防内存泄漏? 第一步:遵循“好”的编程规则“好”的编程规则是各位前辈经验和教训的集合,好的编程规则堪称开发者的“圣经”。遵循统一的编程规则,可以让开发新手少走好多弯路,可以让项目整体的质量维持一个起码的“质量底线”。有关内存泄漏方面的规则主要是“内存管理”方面的,举几个简单的,如下x用malloc或new申请内存之后,立即检查指针值是否为NULL(防止使用指针值为NULL的内存),×动态内存的申请与释放是否配对(防止内存泄漏),x malloc 语句是否正确无误?例如字节数是否正确?类型转换是否正确×是否出现野指针,例如用free或delete释放了内存之后,忘记将指针设置为NULL。 第二步:积极主动检测“内存泄漏”,严格遵循好的编程规则,可以让程序员在代码中尽量少的引入bug,但一旦不小心引入了,怎么办?这就要求我们在单元测试和集成测试中严格把关。在这个阶段,单靠程序员或者测试员通过“代码走查”的方式检查内存泄漏,客户的实践和我的经验告诉我,这是不切实际的,无论效率还是时间。如果能够借助于一些专业的工具的话,情况可能就不一样了。 如果你的程序是用Visual C++ 6.0开发,那么Numega的BoundsChecker将是你检测“内存泄漏”最好的选择,如果是Visual C++.NET,可以试一下Compuware的DevPartner。如果你的程序基于Unix或者Linux平台,使用C或者C++,可以考虑一下开源的工具valgrind,我的朋友跟我说,它在一定程度上比Rational的Purify更出色。上面的工具都要求程序能够动态运行起来,而且测试用例需要你自己准备。 如果你正处于单元测试或集成测试阶段,程序代码量已经足够大,而且还不能够动态运行,要尽早检测代码中的“内存泄漏”问题,该怎么办?此时你可以试用一下目前最新的静态分析技术:×它不要求代码能够动态运行,×也不需要你来编写测试用例,×只需要代码能够正常编译,就可以发现代码只有在执行过程中才出现的错误,当然也包括内存泄漏。 这方面的工具有Klocwork的K7,Coverity的SQS,以及C++test中的BugDetective,其中最“物美价廉”的就是c++test的BugDetective。 如何发现客户端软件的“内存泄漏”?如果开发过程中已经按照我上面提到的去做,相信发布后的程序存在“内存泄漏”的可能性几乎为零。如果开发过程已经到了后期,系统测试已经开始做了,还要发现内存泄漏,这个时候我希望你能够拿到源代码。如果有源代码,你还可以考虑第二步,借助专业的工具协助,虽然可能效果不一定特别理想,但总比下面我提到的方法更好一些。 当然作为测试人员,通常会碰到“需要在系统测试阶段检测是否有内存泄漏,而且没有

几个内存泄漏的例子

几个内存泄漏的例子 ?new和delete要成对使用 ?new和delete要匹配 经常看到一些C++方面的书籍中这样提及到内存泄漏问题,这样的说法的意思是比较明白,但对于初学C++程序员还是很难掌握,所以下面举几个反面的例子,希望对大家有帮助。 例一:错误处理流程中的return导致的内存泄漏 bool MyFun() { CMyObject* pObj = NULL; pObj = new CMyObject(); … if (…) return false; … if(…) return false; … if (pObj != NULL) delete pObj; return true; } 注意:红色字体部分的return之前没有释放pObj,导致内存泄漏。 例二:exception改变了程序的正常流程,导致内存泄漏 情况1: HRESULT MyFun() { HRESULT hr = S_OK; try { CMyObject* pObj = NULL; pObj = new CMyObject(); … if (…) { hr = E_FAIL; throw hr; } … if(…) {

hr = E_FAIL; throw hr; } … if (pObj != NULL) delete pObj; } catch (HRESULT& eHr) { } return hr; } 情况2: void OtherFun() // 可能是自己写的其他函数; // 也可能是其他人写的函数; // 也可能是系统的API; { … if(…) throw exception; … } bool MyFun() { CMyObject* pObj = NULL; pObj = new CMyObject(); … OtherFun(); … if (pObj != NULL) delete pObj; return true; } 注意:上面的两种情况中的throw行为将导致程序的正常流程,一旦有throw的动作发生,pObj对象将不会被正确释放(delete)。 例三:忘记释放系统API创建的资源,导致内存泄露 bool CMyClass::MyFun() { HANDLE hHandle = CreateEvent(NULL,FALSE,TRUE,NULL); … if (…)

Js内存泄漏及解决方案

在IE下的JS编程中,以下的编程方式都会造成即使关闭IE也无法释放内存的问题,下面分类给出: 1、给DOM对象添加的属性是一个对象的引用。范例: var MyObject = {}; document.getElementById('myDiv').myProp = MyObject; 解决方法: 在window.onunload事件中写上: document.getElementById('myDiv').myProp = null; 2、DOM对象与JS对象相互引用。范例: function Encapsulator(element) { this.elementReference = element; element.myProp = this; } new Encapsulator(document.getElementById('myDiv')); 解决方法: 在onunload事件中写上: document.getElementById('myDiv').myProp = null; 3、给DOM对象用attachEvent绑定事件。范例: function doClick() {} element.attachEvent("onclick", doClick); 解决方法: 在onunload事件中写上: element.detachEvent('onclick', doClick); 4、从外到内执行appendChild。这时即使调用removeChild也无法释放。范例: var parentDiv = document.createElement("div"); var childDiv = document.createElement("div"); document.body.appendChild(parentDiv); parentDiv.appendChild(childDiv); 解决方法: 从内到外执行appendChild: var parentDiv = document.createElement("div"); var childDiv = document.createElement("div"); parentDiv.appendChild(childDiv);

Linux下利用Valgrind工具进行内存泄露检测和性能分析

Linux下利用Valgrind工具进行内存泄露检测和性能分析 [日期:2012-06-25] 来源:Linux社区作者:yanghao23 Valgrind通常用来成分析程序性能及程序中的内存泄露错误 一 Valgrind工具集简绍 Valgrind包含下列工具: 1、memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。 2、callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。 3、cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。 4、helgrind:用于检查多线程程序的竞态条件。 5、massif:堆栈分析器,指示程序中使用了多少堆内存等信息。 6、lackey: 7、nulgrind: 这几个工具的使用是通过命令:valgrand --tool=name 程序名来分别调用的,当不指定tool 参数时默认是 --tool=memcheck 二 Valgrind工具详解 1.Memcheck 最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc、free、new、delete的调用都会被捕获。所以,它能检测以下问题: 1、对未初始化内存的使用; 2、读/写释放后的内存块; 3、读/写超出malloc分配的内存块; 4、读/写不适当的栈中内存块; 5、内存泄漏,指向一块内存的指针永远丢失; 6、不正确的malloc/free或new/delete匹配; 7、memcpy()相关函数中的dst和src指针重叠。 这些问题往往是C/C++程序员最头疼的问题,Memcheck能在这里帮上大忙。 例如: #include #include #include void test()

使用 .Net Memory Profiler 诊断 .NET 应用内存泄漏(方法与实践)

使用 .Net Memory Profiler 诊断 .NET 应用内存泄漏(方法与实践) 文章分类:.net编程 关键字: memory leak, .net, .net memory profiler, https://www.360docs.net/doc/342719151.html, 做过应用诊断与优化的朋友都知道内存泄漏和带来的危害,对这种情况的分析和定位一般会比较困难,尤其在 .NET/Java 应用中,隐式的堆内存管理以及托管对象间纷繁复杂的引用关系,使分析和定位问题更加复杂。本文以我的了解,尽量说明了: 1.一种对 .NET/Java 托管内存类应用的内存泄漏分析和诊断方法; 2.使用 .Net Memory Profiler 工具对一个真实 https://www.360docs.net/doc/342719151.html, 应用中存在内存 泄漏问题的分析、诊断实践过程作为示例。 本文包括以下问题、不足: 1.本文以我的现有理解写成,尤其是“方法”相关的内容,每个人在不同情 况下会有不同的方式; 2.不是 .Net Memory Profiler 工具的全面讲解,实践中所涉及的功能仅是 为了定位这里 https://www.360docs.net/doc/342719151.html, 应用中的问题。可参见 .Net Memory Profiler 文档 。 .NET/Java 托管内存类应用的内存泄漏分析和诊断 方法 首先是些科普知识,理解的兄弟请自行快速跳过。 在托管内存管理中,“泄漏”意义不同与传统 Native 应用中的忘记显式释放(delete/delete[] 等)不同,当然对于非托管资源之类(如句柄等)还是需要在 Finalize (析构方法等同于 Finalize)方法中显式释放的,在托管内存管理中“泄漏”对象实例指的是,由于与 Root 对象集中的对象存在本应断开的引用关系,而让 GC 线程认为该对象还被使用,因而不能被释放,尽管其不再会被使用。决大部分情况下,由于应用(程序员)认为该对象不会存在了,而在再次使用时,又在托管堆中再次创建了该对象实例,可以想象这样的

VS2005内存泄漏检测方法

VS2005内存泄漏检测方法 2010-03-09 09:13 247人阅读评论(0) 收藏举报VS2005内存泄漏检测方法 非MFC程序可以用以下方法检测内存泄露: 1.程序开始包含如下定义: view plaincopy to clipboardprint? 1. #ifdef _DEBUG 2. #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) 3. #else 4. #define DEBUG_CLIENTBLOCK 5. #endif // _DEBUG 6. #define _CRTDBG_MAP_ALLOC 7. #include 8. #include 9. #ifdef _DEBUG 10. #define new DEBUG_CLIENTBLOCK 11. #endif // _DEBUG

2.程序中添加下面的函数: view plaincopy to clipboardprint? 1. _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);

1. #ifdef _DEBUG 2. protected: 3. CMemoryState m_msOld, m_msNew, m_msDiff; 4. #endif // _DEBUG 1. #ifdef _DEBUG 2. m_msOld.Checkpoint(); 3. #endif // _DEBUG 4. 5.

java内存泄露、溢出检查方法和工具

JAVA内存泄露、溢出的检查方法、工具介绍 问题发现: 在我们运行的一个项目上线运营后发现运行两天左右就会报内存溢出,只有重启tomcat才能恢复服务,异常信息如下: https://www.360docs.net/doc/342719151.html,ng.OutOfMemoryError: GC overhead limit exceeded https://www.360docs.net/doc/342719151.html,ng.OutOfMemoryError: Java heap space 原因分析: 在此之前必须先介绍一下关于jvm的内存控制,JVM即java虚拟机,它运行时候占用一定的内存,其大小是有限定的,如果程序在运行时jvm占用的内存大于某个限度,则会产生内存溢出,也就是“https://www.360docs.net/doc/342719151.html,ng.outofmemoryerror”。如果jvm内存的没有限度,并且有无限大的内存,那jvm就永远不会出现内存溢出了。很明显无限的内存是不现实的,但是一般情况下我们程序运行过程所需要的内存应该是一个基础固定的值,如果仅是因为我们的项目所需内存超过了jvm设置内存值导致内存溢出,那么我们可以通过增大jvm的参数设置来解决内存溢出的问题。详细处理可参考java jvm的如下参数设置:-Xms -Xmx -Xmn -Xss -Xms: 设置JVM初始内存,此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。 -Xmx:设置JVM最大可用内存。 -Xmn:设置年轻代大小,整个堆大小=年轻代大小+年老代大小+持久代大小.持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8. -Xss:设置每个线程的堆栈大小.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。 在jvm参数调试过程中,发现分配最大内存数超过1G后,仍然会产生内存溢出的现象,而估计其正常分配使用的内存应该不会超过1G,那么由此可以基本断定其存在内存泄露现象,也就是一些原来分配的不再使用的内存不能被java的垃圾回归所回收,导致不断占用原分配的内存而不释放,导致不断申请更多的内存直到超过内存设置而导致内存溢出。

vld内存泄露检测工具介绍及基本原理分析

vld介绍及基本原理分析 作者:何锟 目录 内容导读 (2) 一、vld简介 (2) 二、vld使用方法介绍 (2) 使用步骤 (2) 使用举例 (2) 配置文件(vld.ini)说明 (3) 原理分析分析与思考 (4) 关键技术 (4) 流程分析 (4) 钩子程序分析 (5) 优缺点分析与改进 (6) 优缺点: (6) 改进思考 (6)

内容导读 本文分包括这几个部分: 1、Vld简介 2、Vld使用方法介绍 3、vld原理分析分析 4、vld优缺点分析与改进 一、vld简介 vld全称:Visual Leak Detector 发展历史:2005年~ 2016年,Version 2.5.0 版权:免费、开源 用途:检测windows c/c++程序内存泄露,并且输出详细报告 二、vld使用方法介绍 使用步骤 1、集成到工程 在工程任意位置包含头文件”vld.h”、并且指定静态库路径”vld.lib”,编译时需要宏_DEBUG或VLD_FORCE_ENABLE 2、运行程序 运行环境:debughelp.dll, vld.dll,vld.ini 3、执行测试用例 4、关闭程序时生成了内存测试报告(文本文件或IDE输出窗口) 5、根据报告分析内存泄露 使用举例 源码

编译运行后,可以看到IDE的输出窗口中输出内容 注意:报告还可以输出到txt文件,默认名称为memory_leak_report.txt 配置文件(vld.ini)说明 Vld.ini里面有详细的说明。其中常用的选项有: 1:开启或关闭内存测试 2:报告中是否去掉重复的堆栈 3:函数调用栈的最大深度 4:泄露内存打印的字节数

内存泄露检测工具

1. ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。 2. Dmalloc-Debug Malloc Library. 3. Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。 4. Leaky-Linux下检测内存泄漏的程序。 5. LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。 6. MEMWA TCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。 7. V algrind-Debugging and profiling Linux programs, aiming at programs written in C and C++. 8. KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree. 9. Leak Monitor-一个Firefox扩展,能找出跟Firefox相关的泄漏类型。 10. IE Leak Detector (Drip/IE Sieve)-Drip和IE Sieve leak detectors帮助网页开发员提升动态网页性能通过报告可避免的因为IE局限的内存泄漏。 11. Windows Leaks Detector-探测任何Win32应用程序中的任何资源泄漏(内存,句柄等),基于Win API调用钩子。 12. SAP Memory Analyzer-是一款开源的JA V A内存分析软件,可用于辅助查找JA V A程序的内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。 13. DTrace-即动态跟踪Dynamic Tracing,是一款开源软件,能在Unix类似平台运行,用户能够动态检测操作系统内核和用户进程,以更精确地掌握系统的资源使用状况,提高系统性能,减少支持成本,并进行有效的调节。 14. IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。 15. Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为Microsoft V isual C++的一个插件运行。

内存泄漏的检测、定位和解决经验总结

内存泄漏的检测、定位和解决经验总结 【摘要】 结合局端MCU项目中CSS、NMS模块内存泄漏检测、修正的过程,简要介绍了内存泄漏检测的工具,提出了内存泄漏检测的一些方法(怎样对程序结构进行改造,怎样对程序进行隔离以易于进行内存泄漏检测)。总结了内存泄漏检测过程中成功和失败的体会,希望能对后来者有所启发。 【关键词】 内存泄漏 一、故障或失误概况 局端MCU项目中CSS(Conference Schedule System)、NMS(NetWork Management System)模块自2.03版本起就有内存泄露的问题,开发NGN版本时也花过大量的精力来争取解决这个问题,虽然也修正了一些内存泄漏,但最终检测工具表面现象显示剩下的内存泄露都是所使用的开发库的代码产生的,于是也就大意的认为是所使用的ACE/TAO库本身有内存泄漏,于是无果而终,使这两个模块的内存泄漏问题一直延续到2.03.20x版本。 由于后续测试部和开发部进行测试时引入了Robot来进行自动测试,使业务操作量巨升,此时CSS 模块的内存泄漏问题就更明显了,从程序启动时的13M内存,经过一两个月后可以飙升到200 M左右,正因为此局端MCU项目好几个程序都采用了看门狗的方式来定时检测程序的状态防止程序当掉。 由于问题比较严重,于是再次进行内存泄漏问题的攻关,测试时NMS模块业务操作量小内存泄漏不明显,于是此次攻关重点是查CSS的内存泄漏问题。 此次再次进行CSS行内存泄露问题的研究,力争解决CSS的内存泄露问题,实在找不到解决方案(例如为所使用的开发库的原因)也定位出具体原因供项目组参考。 二、诊断过程 2.1工具介绍 目前Windows平台上流行的内存泄露检测工具有Rational Purify、BoundsChecker、insure++,由于C SS较复杂又是多线程采用Rational Purify工具程序就启动不起来,无法进行检测;parasoft 公司的insure+ +工具传说中比较好用,但由于我们公司没有相应的licence无法使用;最后选择采用限制版的BoundsChec ker来进行检测。

AQTime进行内存泄露和资源泄漏监控

利用AQTime分析.NET程序内存泄露 1.AQTime简介 AQTime是一款著名的,功能强大的Code Profiler工具,它与TestComplete(自动化测试工具)一样,是同属于AutomatedQA公司旗下的软件测试产品,产品含有完整的性能和内存,资源调试工具集,并支持32位及64位机器上的Windows,.NET和JAVA应用程序,同时还支持VBScript和Jscript 代码调试。 AQTime可以帮助程序员理解程序执行过程中运行情况,它内置了大量的调试方案,以及显示面板帮助调试人员隔离以及消除程序的性能问题以及内存、资源泄漏问题,AQTime即可以作为单独的程序启动也可以集成到Microsoft Visual Studio或者Embarcadero RAD Studio(Delphi和C++ Builder的集成开发环境)运行. AQTime的主要功能 ●性能测试 ●内存使用情况监控 ●系统资源使用情况监控 ●代码覆盖率监控 ●兼容性分析 ●程序异常,模块加载,函数调用情况监控 AQTime内置有丰富的调试方案,分为5类(Allocation、Coverage、Performance、Static Analysis、Tracing),共14种调试方案工具集,列举如下: ●Performance Profiler 性能调试方案 提供针对程序中任意范围内的程序段或单行代码进行的性能检测。在程序执行期间,工具自动收集运行时的性能表征数据(如调用次数、执行时间、调用与被调用函数、函数调用层次图、执行期间发生的异常情况等等)。此外,工具提供与运行时间、CPU缓存使用等相关的多种计数器[如Elapsed Time、User Time、User+Kernel Time、CPU Cache Misses、Context Switches等],为了解应用代码级和应用程序级上的性能使用和确定可能存在的性能瓶颈提供详实的参考数据。 ●Allocation Profiler 内存使用分析方案 跟踪程序执行过程中对内存资源的使用情况,按类、对象检测并显示程序中对内存资源的使用情况,确定明确或潜在的内存泄漏来源,避免由此造成的程序问题。

Java程序里的内存泄漏是如何表现的

Java程序里的内存泄漏是如何表现的 大多数程序员都知道使用类似于Java 的编程语言的好处之一就是他们无需再为内存的分配和释放所担心了。你只需要简单地创建对象,当它们不再为程序所需要时Java 会自行通过一个被称为垃圾收集的机制将其移除。这个过程意味着Java 已经解决了困扰其他编程语言的一个棘手的问题-- 可怕的内存泄漏。果真是这样的吗? 在进行深入讨论之前,让我们先回顾一下垃圾收集是如何进行实际工作的。垃圾收集器的工作就是找到程序不再需要的对象并在当它们不再被访问或引用时将它们移除掉。垃圾收集器从贯穿整个程序生命周期的类这个根节点开始,扫描所有引用到的节点。在遍历节点时,它跟踪那些被活跃引用着的对象。那些不再被引用的对象就满足了垃圾回收的条件。当这些对象被移除时被它们占用的内存资源会交还给Java 虚拟机(JVM)。 因此Java 代码的确不需要程序员负责内存管理的清理工作,它自行对不再使用的对象进行垃圾收集。然而,需要记住的是,垃圾收集的关键在于一个对象在不再被引用时才被统计为不再使用。下图对这一概念进行了说明。 上图表示在一个Java 程序执行时具有不同的生命周期的两个类。类A 首先被实例化,它存在的时间比较长,几乎贯穿整个进程的生命周期。在某个时间点,类B 被创建,类A 添加了一个对这个新建类的引用。我们假设类B 是某个用于显示并返回用户指令的用户界面部件。尽管类B 不再被使用,如果类A 对类B 的引用未被清除,类B 将继续存在并占据内存空间,即使下一次垃圾收集被执行。 什么时候需要注意内存泄漏? 如果在你的程序执行一段时间之后遇到https://www.360docs.net/doc/342719151.html,ng.OutOfMemoryError 的话,内存泄漏无疑是最值得怀疑的。除了这种明显的情况之外,什么时候需要考虑内存泄漏?完美主义的程序员会回答说所有的内存泄漏都需要进行审查和更改。然而,在跳到这一结论之前还需要考虑其他几点因素,包括程序的生命周期以及内存泄漏的大小。

LeakCanary傻瓜式的内存泄露检测工具

LeakCa nary傻瓜式的内存泄露检测工具在Android 开发过程中如果需要处理图片或者大量数据的时候,常常会遇到OOM(https://www.360docs.net/doc/342719151.html,ng.OutOfMemoryError),—般出现最多的是在创建Bitmap上,也有可能是在内存中处理了大量的数据造成。 般会针对Bitamp 做下面几种的优化: 1. 增加进程的内存 2. 使用Bitmap.Config.ALPHA_8图片失真) 3 .显示的调用System.gc() 4. catch Exception 5. 调用bitmap.recycle() 6. 缩小bitmap 的大小(如果是读取的原图是一个大图应该先采用这种方式,Bitmap如果是刚好适配屏幕的就不需要缩小了) 7. 使用弱引用和软引用(google已经不建议使用了,Android的GC效率非常高,只要保证对象没有被引用即可) 但是我们会忽略掉一个问题就是什么造成了OOM?—般都发生OOM崩溃的 地方都不一定是内存泄露的地方,崩溃了的原因可能Activity 造成的内存泄露,也可能是操作数据库造成的内存泄露,当内存已经非常接近峰值的时候,这个时候恰巧要创建一个Bitmap对象就会发生OOM(Bitmap对象占用的内存空间比较大)。 内存泄露 每个对象都有自己的生命周期,Activity会调用onDestroy做销毁处理,但 是如果使用Activity的Con text调用Toast就会把这个Activity的引用传给了Toast而Toast的生命周期不会随着Activity的销毁而销毁,这样就造成了Activity 的内存泄露,因为它被Toast引用着。 常见的内存泄露形成的原因:

C++Builder 内存泄漏检查工具

C++Builder 内存泄漏检查工具-CodeGuard 一、为什么写这篇东西 自己在使用BCB5写一些程序时需要检查很多东西,例如内存泄漏、资源是否有释放等等,在使用了很多工具后,发觉BCB5本身自带的工 具――CodeGuard,非常不错,使用也挺方便的,但是摸索了很久(以及翻查了一些资料,包括HELP)才算是会用了。写这篇文章的目的希望有这方面的问题的朋友可以借鉴一下,大家互相学习,共同进步。我的联系方法:Email:szbug@https://www.360docs.net/doc/342719151.html,,希望志同道合的朋友来信互相交流。以下这篇文章算是拼凑出来的一篇文章,一些资料是在书上找的,一些是在HELP上看到了。 二、什么是CodeGuard CodeGuard是在是C++Builder5才出现的一个工具。CodeGuard是C++Builder中一个程序在运行时期的检查器,用于检查内存或者资源的使用,以及函数调用的验证。 CodeGuard可以检测到以下的程序运行期错误: l非法的内存释放。 l无效的句柄或者文件流。 l非法指针。 l使用已被释放的指针。 l内存泄漏。 l分配但最后没有释放的内存变量。 l传递给函数的不正确的参数(包括VCL以及Win32函数)。 l函数返回值的错误。(包括VCL以及Win32函数)。 例如:在应用程序中试图多次释放相同的资源(或者已经释放了的资源)、试图访问已经被释放的内存。 三、在BCB5中怎样使用CodeGuard――配置CodeGuard 如果要使用CodeGuard的话,必须有些代码编译进你的应用程序,所以在改变以下这些设置后。必须全部重新编译(切记切记!!!)。第一、打开应用程序的工程选项的CodeGuard页框,把CodeGuard Validation前面打勾工程选项里,还有其他三个选项。第一个选项允许CodeGuard检查指向局部、全局和静态变量的无效指针和数据溢出。第二个选项允许CodeGuard检测对非法的(无效的、已删除的)对象的方法的调用。第三个选项允许CodeGuard验证内嵌指针的访问(在某些资料上说,开启这个选项会造成程序执行速度变得很慢,我测试过了,如果工程不是很大的话不是很明显,可以接受。)一般的调试是开打所有的选项(默认选择也是全部打开)。 通过CodeGuard的配置工具,可以配置CodeGuard的一些选项,在命令行方式执行CGCONFIG.EXE。可以见到一个对话框 Preferences标签页用于设置CodeGuard这个工具的全局选项。Enable选项可以在应用程序不重新编译的情况下使用或者不使用CodeGuard,一般来说是都是启用她。如果使用CodeGuard的话,建议设置工程选项来禁止或者使用CodeGuard。Stack fill frequency填充栈频率是检测对运行期栈的无效访问。 Report和Error Message Box选项是设置CodeGuard报告错误的方式。在

如何避免内存泄露

如何避免内存泄露 关于内存泄露的原因有很多,最常见的有如下几种: 1、对于通过new等运算符申请到的内存空间在使用之后没有释放掉。关于这个问题,如果 是在过程程序中开辟的空间,我们可以在过程结束时释放;但是如果是面向对象的编程,我们在类的构造函数中开辟的空间,那么我们记得一定要在析构函数中释放,但是如果析构函数出现问题了,导致不能释放内存空间,就造成了内存泄露。 2、对于程序中的windows句柄使用完要close掉。 3、对于内存的泄露有的时候是我们忘记了回收,但是有的时候是我们无法回收,比如1中 提到的析构函数不正确导致内存泄露,这是属于程序有问题;还有关于面向对象编程的一个内存泄露的可能性:一个对象在构造函数中抛出异常,对象本身的内存会被成功释放,但是其析构函数不会被调用,其内部成员变量都可以成功析构,但是用户在构造函数中动态生成的对象无法成功释放(这也在情理之中)。如果一个对象在构造函数中打开很多系统资源,但是构造函数中后续代码抛出了异常,则这些资源将不会被释放,建议在构造函数中加入try catch语句,对先前申请的资源进行释放后(也就是做析构函数该做的事情)再次抛出异常,确保内存和其他资源被成功回收。也就是说构造函数出现问题会导致构造函数中开辟的内存空间不能回收,对于对象本身的内存空间还是可以回收的。 当我们知道这些内存泄露存在的可能性时编写程序的时候就要注意,但是有的时候也会忽略这些问题,那么当发生时,我们如何来检测内存泄露呢? 可以在运行程序后,查看任务管理器,查看“内存使用和“虚拟内存大小”两项,当程序请求了它所需要的内存之后,如果虚拟内存还是持续的增长的话,就说明了这个程序有内存泄漏问题。当然如果内存泄漏的数目非常的小,用这种方法可能要过很长时间才能看的出来。 当然最简单的办法大概就是用CompuWare的BoundChecker之类的工具来检测了,不过这些工具的价格对于个人来讲稍微有点奢侈了。 一般的内存泄漏检查的确是很困难,但是也不是完全没有办法.如果你用VC的库来写东西的话,那么很幸运的是,你已经有了很多检查内存泄漏的工具,只是你想不想用的问题了. Visual C++的Debug版本的C运行库(C Runtime Library)。它已经提供好些函数来帮助你诊断你的代码和跟踪内存泄漏。而且最方便的地方是这些函数在Release版本中完全不起任何作用,这样就不会影响你的Release版本程序的运行效率。 比如下面的例子里面,有一个明细的内存泄漏。当然如果只有这么几行代码的话,是很容易看出有内存泄漏的。但是想在成千上万行代码里面检查内存泄漏问题就不是那么容易了。 char *pstr=new char[5]; lstrcpy(pstr, "Memory leak "); 我们如果我们在Debug版本的Code里面对堆(Heap)进行了操作,包括malloc,free,calloc,realloc,new和delete可以利用VC Debug运行时库中堆Debug函数来做堆的完整性和安全性检查。比如上面的代码,lstrcpy的操作明显破坏了pstr的堆结构,使其溢出,并破坏了临近的数据。那我们可以在调用lstrcpy之后的代码里面加入_CrtCheckMemory函数。_CrtCheckMemory函数发现前面的lstrcpy使得pstr的堆结构被破坏,会输出这样的报告: memory check error at 0x00372FA5=0x79, should be 0xFD. memory check error at 0x00372FA6=0x20, should be 0xFD. memory check error at 0x00372FA7=0x6C, should be 0xFD. memory check error at 0x00372FA8=0x65, should be 0xFD.

性能测试之内存泄漏

性能测试之内存泄漏 上一篇 / 下一篇 2011-01-04 11:17:58 / 个人分类:性能测试 查看( 709 ) / 评论( 4 ) / 评分( 1 / 0 ) 关于内存泄漏,相信大家都不陌生,压力测试中经常会出现,本人最近在做一个压力测试中就着实体会了一下,上来分享分享。 内存泄露是指程序中间动态分配了内存,但是在程序结束时没有释放这部分内存,从而造成那一部分内存不可用的情况,重起计算机可以解决,但是也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起的。 以发生的方式来分类,内存泄漏可以分为4类: 1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。 2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。 3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。 4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。 本人最近就在对一个Http应用进行压力测试,发现被测试的对象进程在并发100时内存占用达到20%,当压力到达1000的时候,内存就持续上升,达到60%,最后压力结束后,内存仍旧停留在60%的使用率,然后重启了系统发现内存已经恢复了正常,于是在第二轮测试时再次不断加压,同时关注性能计数器中的如下指标: Memory\ Available Bytes 是指剩余的可用物理内存,单位是兆字节(参考值:>=10%)。表明进程当前可使用的内存字节数。 Memory\ Pages/sec 是表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放工作集空间的页面数。

相关文档
最新文档