什么是内存泄漏
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的工内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
请解释一下“内存泄漏”,这个问题会有什么影响
申请了内存不释放就是内存泄露 比如 void GetMemory(int len) { int p =new int[len]; } p申请了内存,但是函数返回了,没有指针的首地址传出来,不能释放了
内存泄漏是什么意思?简单说说就行了。
简单说 内存中的某一块正在被其他程序使用 这时如果再有其他程序试图使用这块内存 就会发生内存泄露
内存泄漏是指_______
选D项,实际上是堆内存分配后,至最终都没有被回收,始终被占用
最典型的例子是使用new分配内存,在整个程序中一直没有使用delete销毁,这就造成了使用new分配的那部分堆内存始终被占用(没有被释放)
内存泄露有一点想不明白,到底什么样才算内存泄漏
工具-选项-高级-更新-Firefox的对号去掉就行了。事实上30以后的版本对内存的管理更好了,内存泄露已经很少见了,但对于内存的最小值要求貌似更高一些,我曾经在256内存的电脑上使用36没什么问题,当然,由于cpu不足引起的flash响应慢就不算了。再小的内存就没用过了,不知道什么样。
什么是内存溢出与内存泄露,几种常见导致内存泄露的
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出
以发生的方式来分类,内存泄漏可以分为4类:
1 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
2 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或 *** 作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
3 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
4 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到
内存溢出的原因以及解决方法
引起内存溢出的原因有很多种,我列举一下常见的有以下几种:
1内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2 类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3代码中存在死循环或循环产生过多重复的对象实体;
4使用的第三方软件中的BUG;
5启动参数内存值设定的过小
内存溢出的解决方案:
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看逗OutOfMemory地错误前是否有其它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
重点排查以下几点:
1检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查>>
java内存泄露,是什么意思
内存泄露是指你申请了内存空间但是没有控制释放,然后那一块内存就被荒废了,你自己不用了,别人也用了不了,结果内存就被你占满了
什么是内在泄露内存泄露了会有什么后果
内存泄漏是主内存分配了部分内存后而没有释放,逐渐耗尽内存资源,导致系统崩溃。它的后果甚至是会影响到以后内存的正常运行或使用内存损坏~~~ 它主要是指程序中间动态分配了内存,但是在程序结束时没有释放这部分内存,从而造成那一部分内存不可用的情况,重起计算机可以解决,但是也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件引起的。而在一般情况下无法轻易被发现的其实它也是轻易不是出现的,它就好象你坐在一个升降机里所在是13楼而你还按下13楼的按扭一样,内存泄露只会在这样的情况下出现的,不过内存泄露或者内存泄漏说还是会比一个人站在13楼还按要去13楼的按扭这样的情况要多的多,因为有时内存泄漏会时常发生在用户使用某些较大且较复杂的程序中~~~~处理的办法也只有使用一些软件来测试内存有没有这样泄露的问题了~~~~~不过要是隐性式的内存泄漏就不太好办了~~~要根据当前发生一些问题或是一些 *** 作来判断是否发生内存泄漏的问题
c++中中内存泄露有什么危害?
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害。作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积。而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄礌它更难被检测到。存在内存泄漏问题的程序除了会占用更多的内存外,还会使程序的性能急剧下降。对于服务器而言,如果出现这种情况,即使系统不崩溃,也会严重影响使用。
不过还有一点,如果你的程序内存泄露正好写到了系统使用的内存或者其他程序使用的内存地址,那么就会导致系统异常或者程序崩溃
什么是内存泄漏 如何避免
内存泄漏的定义: 对象不再被应用程序使用,但是垃圾回收器却不能移除它们,因为它们正在被引用。
如何阻止内存泄漏?
以下是一些阻止内存泄漏的快速动手技巧。
(1)注意 类,例如HashMap,ArrayList,等等。因为它们是内存泄漏经常发生的地方。当它们被声明为静态时,它们的生命周期就同应用程序的生命周期一般长。
(2)注意事件监听器和回调,如果一个监听器已经注册,但是当这个类不再被使用时却未被注销,就会发生内存泄漏。
(3)“如果一个类管理它自己的内存,程序员应该对内存泄漏保持警惕。”[1] 很多时候当一个对象的成员变量指向其他对象时,不再使用时需要被置为null。
希望这个回答对你有帮助
方法/步骤
1
用xcode打开自己的工程,按快捷键command+r 运行需要测试的程序。
2
点击xcode导航栏的“show the debug navigator”,切换到debug模式
然后选中“Memory”,再点击右侧的 “Profile in Instruments”,会自动打开Instruments。
这时候会d出来一个对话框,选择“Transfer”
打开后,这时界面如图:
然后切换到iOS模拟器,点击那个测试按钮
这个时候会d出一个对话框,
“cancel”取消对话框后,多点几次“button”,切换到Instruments会发现 “Leaks”一栏里有几个红色的区块。
这就是内存泄露了。
点击暂停,
然后点击“Leaks”一栏
然后点击“导航栏”切换到“call tree”模式下
看到列表里列出了内存泄露的调用逻辑:
勾选右边的详细窗口中的“hide system libraries”,隐藏系统函数。
这个时候就可以清楚看到我们自己程序中的方法调用层次结构了。
展开后,可以发现是[ViewController onTestLeakBtn]
鼠标双击“[ViewController onTestLeakBtn ]”这一行,会跳转到代码。
剩下的工作就是修改代码,然后重复以上步骤。直到没有内存泄露为止。
一、内存泄漏的检查方法:
1ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。
2Dmalloc-Debug Malloc Library
3Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。
4Leaky-Linux下检测内存泄漏的程序。
5LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。
6MEMWATCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。
7Valgrind-Debugging and profiling Linux programs, aiming at programs written in C and C++
8KCachegrind-A visualization tool for the profiling data generated by Cachegrind and Calltree
9IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。
二、内存泄漏的简单介绍:
内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。
内存泄漏形象的比喻是“ *** 作系统可提供给所有进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以“内存泄漏”是从 *** 作系统的角度来看的。这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。
p=new int; //p指针修改,原来申请内存的地址没有记录下来,于是无法释放 下面介绍如何检查内存泄漏:1包含头文件和定义#define _CRTDBG_MAP_ALLOC //并非绝对需要该语句,但如果有该语句,打印出来的是文件名和行数等更加直观的信息#include <stdlibh>#include <crtdbgh>(1)#include语句必须采用上文所示顺序。如果更改了顺序,所使用的函数可能无法正确工作(2)如果有cpp文件无法看到这三行,以下函数就无效了,于是应该把这三行放到一个头文件里,确保每个cpp文件会调用到它2方法一:使用_CrtDumpMemoryLeaks()int main(int argc , char argv[]){{new int;}_CrtDumpMemoryLeaks();return 0;}output:Detected memory leaks!
Dumping objects ->
{49} normal block at 0x00384DA8, 4 bytes long
Data: < > CD CD CD CD
Object dump complete其内容包括:内存分配型号(在大括号内)、块类型(普通、客户端或 CRT)、 十六进制形式的内存位置、以字节为单位的块大小、以字节为单位的块大小、前 16 字节的内容(十六进制)注意:(1)大括号的位置,如果不加{new int;},这块内存是等到main函数结束才泄漏的,而_CrtDumpMemoryLeaks()是在main函数里调用的,于是判断内存泄漏class A{public:int Data;A(){Data=new int;}~A(){delete Data;}};int main(int argc , char argv[]){A Test;_CrtDumpMemoryLeaks();return 0;}output:Detected memory leaks!
Dumping objects ->
{49} normal block at 0x00384DA8, 4 bytes long
Data: < > CD CD CD CD
Object dump complete(2)对于一些全局函数,如果初始化时申请了内存,到程序结束时候才释放,此函数会一直把新申请的内存当作泄漏来对待A Test;
int main(int argc , char argv[]){_CrtDumpMemoryLeaks();return 0;}output:Dumping objects ->
{49} normal block at 0x00384DA8, 4 bytes long
Data: < > CD CD CD CD
Object dump complete2方法二:在程序入口写几个语句,程序退出时,如果发现有内存泄漏,会自动在DEBUG OUTPUT窗口和DebugView中输出内存泄漏信息int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag( tmpFlag );3方法三:使用_CrtMemCheckpoint(),可以查出某程序段的内存泄漏情况int main(int argc , char argv[]){CrtMemState s1, s2, s3;
_CrtMemCheckpoint( &s1 );
new int; //程序段 _CrtMemCheckpoint( &s2 );
if ( _CrtMemDifference( &s3, &s1, &s2) ) _CrtMemDumpStatistics( &s3 );return 0;}output: bytes in 0 Free Blocks
4 bytes in 1 Normal Blocks
0 bytes in 0 CRT Blocks
0 bytes in 0 Ignore Blocks
0 bytes in 0 Client Blocks
JetBrains dotMemory,用这个工具。
有两个前提
net版本必须在40以上
你必须首先自己要做一些排查,定位到可能造成内存泄漏的地方。然后用这个工具,采集快照,这个工具能分析出某一时刻,内存使用情况,各个对象占用内存情况
要想检测内存泄漏,就必须对程序中的内存分配和释放情况进行记录,所能够采取的办法就是重载所有形式的operator new 和 operator delete,截获 new operator 和 delete operator 执行过程中的内存 *** 作信息。下面列出的就是重载形式
void operator new( size_t nSize, char pszFileName, int nLineNum )
void operator new[]( size_t nSize, char pszFileName, int nLineNum )
void operator delete( void ptr )
void operator delete[]( void ptr )
我们为 operator new 定义了一个新的版本,除了必须的 size_t nSize 参数外,还增加了文件名和行号,这里的文件名和行号就是这次 new operator *** 作符被调用时所在的文件名和行号,这个信息将在发现内存泄漏时输出,以帮助用户定位泄漏具体位置。对于 operator delete,因为无法为之定义新的版本,我们直接覆盖了全局的 operator delete 的两个版本。
在重载的 operator new 函数版本中,我们将调用全局的 operator new 的相应的版本并将相应的 size_t 参数传入,而后,我们将全局 operator new 返回的指针值以及该次分配所在的文件名和行号信息记录下来,这里所采用的数据结构是一个 STL 的 map,以指针值为 key 值。当 operator delete 被调用时,如果调用方式正确的话(调用方式不正确的情况将在后面详细描述),我们就能以传入的指针值在 map 中找到相应的数据项并将之删除,而后调用 free 将指针所指向的内存块释放。当程序退出的时候,map 中的剩余的数据项就是我们企图检测的内存泄漏信息--已经在堆上分配但是尚未释放的分配信息。
以上就是内存检测实现的基本原理,现在还有两个基本问题没有解决:
1) 如何取得内存分配代码所在的文件名和行号,并让 new operator 将之传递给我们重载的 operator new。
2) 我们何时创建用于存储内存数据的 map 数据结构,如何管理,何时打印内存泄漏信息。
先解决问题1。首先我们可以利用 C 的预编译宏 __FILE__ 和 __LINE__,这两个宏将在编译时在指定位置展开为该文件的文件名和该行的行号。而后我们需要将缺省的全局 new operator 替换为我们自定义的能够传入文件名和行号的版本,我们在子系统头文件 MemRecordh 中定义:
#define DEBUG_NEW new(__FILE__, __LINE__ )
而后在所有需要使用内存检测的客户程序的所有的 cpp 文件的开头加入
#include "MemRecordh"
#define new DEBUG_NEW
就可以将客户源文件中的对于全局缺省的 new operator 的调用替换为 new (__FILE__,__LINE__) 调用,而该形式的new operator将调用我们的operator new (size_t nSize, char pszFileName, int nLineNum),其中 nSize 是由 new operator 计算并传入的,而 new 调用点的文件名和行号是由我们自定义版本的 new operator 传入的。我们建议在所有用户自己的源代码文件中都加入上述宏,如果有的文件中使用内存检测子系统而有的没有,则子系统将可能因无法监控整个系统而输出一些泄漏警告。
再说第二个问题。我们用于管理客户信息的这个 map 必须在客户程序第一次调用 new operator 或者 delete operator 之前被创建,而且在最后一个 new operator 和 delete operator 调用之后进行泄漏信息的打印,也就是说它需要先于客户程序而出生,而在客户程序退出之后进行分析。能够包容客户程序生命周期的确有一人--全局对象(appMemory)。我们可以设计一个类来封装这个 map 以及这对它的插入删除 *** 作,然后构造这个类的一个全局对象(appMemory),在全局对象(appMemory)的构造函数中创建并初始化这个数据结构,而在其析构函数中对数据结构中剩余数据进行分析和输出。Operator new 中将调用这个全局对象(appMemory)的 insert 接口将指针、文件名、行号、内存块大小等信息以指针值为 key 记录到 map 中,在 operator delete 中调用 erase 接口将对应指针值的 map 中的数据项删除,注意不要忘了对 map 的访问需要进行互斥同步,因为同一时间可能会有多个线程进行堆上的内存 *** 作。
好啦,内存检测的基本功能已经具备了。但是不要忘了,我们为了检测内存泄漏,在全局的 operator new 增加了一层间接性,同时为了保证对数据结构的安全访问增加了互斥,这些都会降低程序运行的效率。因此我们需要让用户能够方便的 enable 和 disable 这个内存检测功能,毕竟内存泄漏的检测应该在程序的调试和测试阶段完成。我们可以使用条件编译的特性,在用户被检测文件中使用如下宏定义:
#include "MemRecordh"
#if defined( MEM_DEBUG )
#define new DEBUG_NEW
#endif
当用户需要使用内存检测时,可以使用如下命令对被检测文件进行编译
g++ -c -DMEM_DEBUG xxxxxxcpp
就可以 enable 内存检测功能,而用户程序正式发布时,可以去掉 -DMEM_DEBUG 编译开关来 disable 内存检测功能,消除内存检测带来的效率影响。
(1) *** 作Bitmap对象,一定要注意,在不使用的时候 recycle
(2) 访问数据库,一定要记得关闭游标
(3) 涉及JNI层的代码,由于JNI层是采用C/C++编写,需要自己管理内存的分配/回收,所以要慎重小心。
那么,Android开发中,有什么有效的方法可以检测内存使用情况以及内存泄漏呢?
这里主要介绍三种方法:
1 程序的Log信息
程序在进行垃圾回收的时候,会打印一条Log信息(logcat窗口),例如:
D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
注意这条信息中的 “ 3571K/9991K” 值,这代表着程序使用的heap大小,如果这个值一直在增加,而从来不减小,那么就代表着你的程序存在着内存泄漏。
2 DDMS的Heap信息
Eclipse开发环境还提供了一种更加直观的方法来查看App的Heap信息, *** 作方式如下:
(1) 连接手机,运行程序,假设是 comtickticktest 程序
(2) 点击DDMS按钮,在左侧的Device窗口选中你要检测的程序(comtickticktest )
(3) 点击Device窗口工具栏的第二个图标(Update Heap),
(4) 点击右边的窗口的Cause GC按钮,即可得到当前程序的Heap信息
同样,随着程序的运行,多次点击得到的Heap大小,如果只增不减的话,也昭示着你的程序有内存泄漏。
3 adb命令查看内存信息
其实,最全面最简单的方式还是用adb命令来查看程序的内存占用和内存泄漏情况,打开命令行窗口,adb命令的格式如下:
adb shell dumpsys meminfo <package_name>
其中,package_name 也可以换成程序的pid,pid可以通过 adb shell top | grep app_name 来查找,在命令行窗口运行上述命令,得到的我的 comtickticktest 程序的内存情况如下所示:
这里得到的信息非常多,重点关注如下几个字段:
(1) Native/Dalvik 的 Heap 信息
具体在上面的第一行和第二行,它分别给出的是JNI层和Java层的内存分配情况,如果发现这个值一直增长,则代表程序可能出现了内存泄漏。
(2) Total 的 PSS 信息
这个值就是你的应用真正占据的内存大小,通过这个信息,你可以轻松判别手机中哪些程序占内存比较大了。
4 总结
关于Android开发中内存的使用情况和内存泄漏的检测就简单介绍到这里,基本上用以上三种方式都能够定位内存泄漏问题,平时在使用Bitmap,数据库和JNI层C/C++编程的时候,注意一点就行。另外,如果想深入了解文中的一些详细内容,可以参考Google官方提供的两篇文章,它们有着更详细的论述《Investigating Your RAM Usage》,《Managing Your App Memory》,有任何疑问或者不清楚的地方,欢迎留言或者来信lujunhust@gmailcom交流。
以上就是关于内存泄漏是什么全部的内容,包括:内存泄漏是什么、怎么测试ios app的内存泄漏、怎样发现内存泄露等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)