您好,欢迎访问三七文档
1内存泄漏检测2主要内容内存泄漏定义内存泄漏原因分析内存泄漏检测方法内存泄漏检测工具内存泄漏的防范讨论3内存泄漏的定义程序中的内存结构程序中内存分为堆、栈、全局/静态存储区和常量存储区.全局常量位于常量存储区.全局变量位于静态数据区.局部变量以及函数参数变量位于栈.使用new/malloc分配的内存位于堆上.•……•栈•……•代码区•静态数据区•高端内存区域•……•常量存储区•堆•低端内存区域•常量存储区域和静态数据区域的内存在程序退出时释放•栈中分配的内存在变量离开其作用域时释放•堆中分配的内存必须显示的释放4内存泄漏的定义内存泄漏的定义程序中从堆中分配的内存在使用完毕后忘记释放,从而失去对该块内存的控制,导致该块内存一直被占用直至程序退出。程序一直分配内存,直到程序退出才释放所有内存。内存泄漏的危害程序占用内存越来越多,使得整个系统运行速度越来越慢。糟糕者可用内存耗尽,应用程序崩溃。5内存泄漏的定义内存泄漏的分类常发性内存泄漏•发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。一次性内存泄漏•发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。偶发性内存泄漏•发生内存泄漏的代码只会被执行一次隐式内存泄漏•程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存6内存泄漏原因分析new出来的对象没有delete代码中没有delete的地方指针被重新赋值了,赋值前没有delete逻辑分支考虑不全。函数内部逻辑考虑不周。接口调用时序逻辑考虑不全CUDPSocket*CreateUdpSocket(conststd::string&sIpAdress,UINTnLocalAudioPort){CUDPSocket*pUdpSocket=newCUDPSocket();CInetAddressoInetAddress(sIpAddress);SOCKERRORerr=pUdpSocket-Create(&oInetAddress,nLocalAudioPort);if(SOCKET_SUCCESS!=err){//deletepUdpSocket;//pUdpSocket=0;returnNULL;}returnpUdpSocket;}内存泄漏原因分析基类析构函数非虚当基类指针指向派生类对象,delete该基类指针时派生类对象的析构不会被调用。如果派生类中使用了stl容器或者从堆中分配内存的作为成员变量,那么内存泄漏就悄无声息的发生了。7classCIavpMsg{public:CIavpMsg(){}~CIavpMsg(){printf(~CIavpMsg()\r\n);}};classCLogMsg:publicCIavpMsg{public:CLogMsg(){}~CLogMsg(){printf(~CLogMsg()\r\n);}public:stringm_sTime;};int_tmain(intargc,_TCHAR*argv[]){CIavpMsg*pMsg=newCLogMsg();string&sTime=((CLogMsg*)pMsg)-m_sTime;intnCapacity=sTime.capacity();printf(sTime初始内存大小:%d\r\n,nCapacity);sTime=2010年月日:18:01;nCapacity=sTime.capacity();printf(sTime赋值内存大小:%d\r\n,nCapacity);constchar*pStr=sTime.c_str();deletepMsg;printf(LogMsg对象删除后m_sTime的内容:%s\r\n,pStr);return0;}内存泄漏原因分析8内存泄漏原因分析delete一个只有声明没有定义的类为了避免C/C++头文件中包含很多的其他头文件,通常将关联到的其他类型声明一下即可,在真正使用的地方包含其类定义的头文件。如果在某个地方delete一个只有声明,而没有包含其类定义的头文件,那么该delete将不会去调用该类的析构函数。其结果和基类析构非虚导致派生类的析构不被调用的后果一样。9#pragmaonceclassCIavpMsg;classCIavpMsgFactory{public://从网络收到的消息创建成一个IavpMsgCIavpMsg*DynamicCreateMsg(constchar*pMsgStream,intnStreamLen);};#includestdafx.h#includeiavpmsgfactory.hint_tmain(intargc,_TCHAR*argv[]){CIavpMsgFactoryoMsgFactory;CIavpMsg*pMsg=oMsgFactory.DynamicCreateMsg(0,0);//DoSomeThingWithIavpMsg(pMsg);deletepMsg;return0;}内存泄漏原因分析向容器中不断的添加内容,而不删除内容。写代码时疏忽,逻辑判断不正确导致此种情况发生。接口设计不良,容器删除的职责不明。10内存泄漏原因分析11classCTTSPlayer{public:TTSPlayTaskIDPrepareTask(constchar*ttstext,TtsPlayResultHandler&handler,void*param,constPlayEndPoint&endPoint){CTTSPlayerThread*pPlayerThread=newCTTSPlayerThread();m_oTTSPlayerMap[m_nID++]=pPlayerThread;returnm_nID;}voidPlay(TTSPlayTaskIDtaskID){//1.从容器中找到playthread//2.异步调用playthread的play接口}voidStop(TTSPlayTaskIDtaskID){//1.从容器中找到playthread//2.deleteplaythread//3.从容器中删除playthread}private:std::mapTTSPlayTaskID,CTTSPlayerThread*m_oTTSPlayerMap;TTSPlayTaskIDm_nID;};Play失败,异步通知给调用者,调用者认为Play已经失败,没有必要再去调用Stop接口了,map容器中保存的对象永远不会被删除了,直至程序退出,从而导致内存泄漏!内存泄漏原因分析指针所有权不明函数返回一个指针,却没说明该谁释放。12classCRtspClient{public://其他方法声明//向RTSP服务器发送Option消息,返回服务器的响应结果char*SendOption();private://成员变量声明};返回值要不要delete?内存泄漏原因分析SDK或第三方库使用不当FormatMessage方法指定FORMAT_MESSAGE_ALLOCATE_BUFFER则该方法得到的字符串为系统分配,需要LocalFree释放该字符串。13int_tmain(intargc,_TCHAR*argv[]){TCHAR*buffer=newTCHAR[100];TCHAR*pClone=buffer;ZeroMemory(pClone,100);TCHAR*s=origorigorigorig;memcpy(pClone,s,strlen(s));DWORDerror=ERROR_STACK_OVERFLOW;DWORDdwRet=::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,error,0,(LPTSTR)&buffer,0,NULL);printf(%s\r\n,buffer);printf(%s\r\n,pClone);//LocalFree(buffer);return0;}内存泄漏检测方法代码检查所有的new有没有对应的delete?基类的析构是否是虚函数?代码逻辑是否存在漏洞?调用第三方库接口或者SDK的方法是否正确合理?仔细阅读编译结果,不要忽视warning.14warningC4150:删除指向不完整“CIavpMsg”类型的指针;没有调用析构函数Warning:代码检查需仔细,每一行都要认真推敲,切忌走马观花!内存泄漏检测方法单元测试第三方提供的库只有接口,没有源码。通过代码检查发现了可疑泄漏模块,对该模块写一个简单单元测试程序,进行压力测试,通过观察内存占用曲线,确定该模块是否存在泄漏。15成功案例:iAvp2.4开发中对nuance的opencalllog和closecallog的接口进行单元测试,发现nuance此处存在泄漏。内存泄漏检测方法使用内存泄漏检测工具在Windows平台下,内存泄漏检测工具一般有三种。内存实时监控,如iAvp的showin工具;MSC-RuntimeLibrary内建的检测功能;外挂式的检测工具,诸如Purify,BoundsChecker等;16内存泄漏检测工具内存实时监控,如iAvp的showin工具定时检测内存占用情况,绘制成内存占用曲线。根据曲线的斜率,显示内存泄漏严重程度。无法定位内存泄漏的代码。17内存泄漏检测工具MSC-RuntimeLibrary内建的检测功能使用MSC-RuntimeLibrary调试堆函数。181.要使用crt的调试堆函数,首先在程序添加如下语句:2.程序退出的地方调用_CrtDumpMemoryLeaks:_CrtDumpMemoryLeaks();#define_CRTDBG_MAP_ALLOC#includestdlib.h#includecrtdbg.h语句顺序不可改变3.程序有多个出口时无需在每个出口调用_CrtDumpMemoryLeaks,程序的开始处调用_CrtSetDbgFlag即可:_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);内存泄漏检测工具MSC-RuntimeLibrary内建的检测功能内存泄漏报告输出191._CrtDumpMemoryLeaks报告默认输出到VS调试输出窗口。问题1:必须在VSIDE上以调试的方式运行,对于需要进行压力测试的程序非常不方便。问题2:在IDE的调试输出窗口分析泄漏报告很不方便。2.改变内存泄漏报告的输出位置。freopen(sDumpFile,w,stderr);_CrtSetReportMode(_CRT_WARN,_CRTDBG_MODE_FILE);_CrtSetReportFile(_CRT_WARN,_CRTDBG_FILE_STDERR);_CrtDumpMemoryLeaks();fclose(stderr);内存泄漏检测工具MSC-RuntimeLibrary内建的检测功能内存泄漏报告分析201.应用程序没有定义_CRTDBG_MAP_ALLOC,报告输出如下:Detectedmemoryleaks!Dumpingobjects-{18}normalblockat0x00780E80,64byteslong.Data:CDCDCDCDCDCDCDCDCDCDObjectdumpcomplete.Detectedmemoryleaks!Dumpingobjects-C:\leaktest\leaktest.cpp(20):{18}normalblockat0x00780E80,64byteslong.
本文标题:手机内存检测
链接地址:https://www.777doc.com/doc-3472171 .html