程序时不时的出现ios内存泄露怎么解决如何调试解决问题

VC &&&&最新内容
VC &&&&随机内容vc2010开发的mfc单文档程序,关闭时,提示内存泄露,该怎么解决_读书人
vc2010开发的mfc单文档程序,关闭时,提示内存泄露,该怎么解决
&来源:读书人网&【读书人网():综合教育门户网站】
vc2010开发的mfc单文档程序,关闭时,提示内存泄露用vc2010开发的mfc单文档程序,使用了多线程、sql server200
vc2010开发的mfc单文档程序,关闭时,提示内存泄露用vc2010开发的mfc单文档程序,使用了多线程、sql server2000、UDP收发数据,程序关闭退出时,提示内存泄露:Detected memory leaks!Dumping objects -&f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {188279} normal block at 0x bytes long. &Data: & x & 84 CF B1 78 13 00 00 00 13 00 00 00 01 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {187156} normal block at 0x033FA058, 26 bytes long. &Data: & x & 84 CF B1 78 04 00 00 00 04 00 00 00 02 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {187151} normal block at 0x06 bytes long. &Data: & x & 84 CF B1 78 C2 00 00 00 C2 00 00 00 01 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(188) : {187149} normal block at 0x0 bytes long. &Data: & x% % & 84 CF B1 78 25 00 00 00 25 00 00 00 03 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {187148} normal block at 0x, 88 bytes long. &Data: & x# # & 84 CF B1 78 23 00 00 00 23 00 00 00 01 00 00 00& {186975} normal block at 0x bytes long. &Data: &H 9 s@ dA X6A & 48 C8 39 03 10 73 40 03 F0 64 41 03 58 36 41 03& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186974} normal block at 0x, 38 bytes long. &Data: & x & 84 CF B1 78 0A 00 00 00 0A 00 00 00 02 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186911} normal block at 0x, 38 bytes long. &Data: & x & 84 CF B1 78 0A 00 00 00 0A 00 00 00 01 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186904} normal block at 0x, 182 bytes long. &Data: & xR R & 84 CF B1 78 52 00 00 00 52 00 00 00 01 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186893} normal block at 0x bytes long. &Data: & x & 84 CF B1 78 0D 00 00 00 0D 00 00 00 01 00 00 00& {186889} normal block at 0x, 8 bytes long. &Data: & $ & 9C F4 24 06 00 00 00 00& {186887} normal block at 0x bytes long. &Data: & s@ X6A 9 & 10 73 40 03 58 36 41 03 E0 C7 39 03& {186885} normal block at 0x, 8 bytes long. &Data: & $ & F8 F4 24 06 00 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186880} normal block at 0x04 bytes long. &Data: & xX X & 84 CF B1 78 58 00 00 00 58 00 00 00 01 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186879} normal block at 0x033D8E88, 20 bytes long. &Data: & x & 84 CF B1 78 01 00 00 00 01 00 00 00 01 00 00 00& {186878} normal block at 0x bytes long. &Data: & s@ X6A 9 & 10 73 40 03 58 36 41 03 E0 C7 39 03& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(188) : {186877} normal block at 0x, 44 bytes long. &Data: & x & 84 CF B1 78 0A 00 00 00 0D 00 00 00 04 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(188) : {186869} normal block at 0x bytes long. &Data: & x & 84 CF B1 78 0A 00 00 00 0D 00 00 00 03 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(188) : {186861} normal block at 0x bytes long. &Data: & x & 84 CF B1 78 0A 00 00 00 0D 00 00 00 04 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186854} normal block at 0x bytes long. &Data: & x & 84 CF B1 78 01 00 00 00 01 00 00 00 01 00 00 00& {186853} normal block at 0x, 8 bytes long.
&Data: &P $ & 50 F6 24 06 00 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(156) : {186852} normal block at 0x, 36 bytes long. &Data: & x & 84 CF B1 78 09 00 00 00 09 00 00 00 02 00 00 00& f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp(306) : {32379} client block at 0x, subtype c0, 68 bytes long.a CWinThread object at $, 68 bytes longObject dump complete.请大家帮忙看看,什么地方出了问题?如何解决?[解决办法]……这怎么可能就直接能看出来?不过多线程的话,不是正常结束的进程,而是在调试过程中直接中止,很容易出现内存泄露的[解决办法]找个内存泄露测试查查[解决办法]检查你所有调用过new的位置看看对应的delete有没有问题[解决办法]建议楼主检查所有的CString::GetBuffer函数调用之后是否都用了CString::ReleaseBuffer进行释放。[解决办法]可以用鼠标在其中的一个提示上双击,一般就会跳到泄露内存的地方,这样就可以看出是哪个变量没被释放,另外,可以先把操作的代码屏蔽掉,看看还有没有,如果还有,就再屏蔽UDP通信,一个一个试,逐渐缩小范围查找当主线程创建一个辅助线程的时候,如果当我关闭应用程序(关闭主线程),主线程会关闭辅助线程,但是若辅助线程里有个函数执行时间相当长,当然主线程也会灭掉辅助线程,但是会导致内存泄露!当我按F5调试运行,会看到很多的内存泄露,该怎么办啊?
回复讨论(解决方案)
不太明白lz的意思~
主线程结束,整个进程都结束了~什么资源都释放了~
你一定是强行终止了线程!
强行终止系统不会知道有泄露的,肯定还是你程序的问题,根据泄露的提示信息一般猜出一些端倪
只要线程终止,主程序也就终止了,系统会回收资源啊!
是调用了TERMINATE来终止的吧
这不行的,会导致泄露
应该用一个volatile变量来指示线程什么时间退出
如果是消息驱动的,那么应该在耗费时间的函数中检测这个volatile,防止无限制等待
反正一定要让线程自己返回,否则无法知道会发生什么问题
skt01(skt001)和niying(逆颖)的说法是不正确的。
vc中显示内存泄漏是调试器机制,可以注意到打印信息是在.exe中止之前出现的,调试器自然知道你有哪些内存没释放(通过重载new&和delete实现)。
那么自然,如果子线程中用过new,这时候主线程需要退出,先杀死子线程(系统使用了Terminate),那么内存肯定泄漏了。
关键是程序实现方法有问题,主线程应该等待子线程完成工作(waitfor...),然后再退出。其实内存还好说,退出也就退出了,但如果是其他,比如文件,就可能有意想不到的结果。所以需要等待子线程完成工作,当然如果是调试时强制中止主线程,内存泄漏当然无法避免。
关键是程序实现方法有问题,主线程应该等待子线程完成工作(waitfor...),然后再退出。其实内存还好说,退出也就退出了,但如果是其他,比如文件,就可能有意想不到的结果。所以需要等待子线程完成工作,当然如果是调试时强制中止主线程,内存泄漏当然无法避免。
=============================
同意这种说法~呵呵
主线程结束那么程序也就结束了,操作系统会帮你把所有的资源都回收的,即使是强行退出。但是如果主线程没有结束,只是他创建的子线程结束了,那么就会造成内存泄漏,内存泄漏是因为在堆上动态创建了内存,所以检查一下你的new或者malloc的应用,是否有对应的释放就可以查处来了。
各位大哥,先什么都不要管,我做了个测试才发帖子问这个问题的:我建立了一个基于对话框应用程序,放了一个按钮,当点击这个按钮时,启动一个新的线程:AfxBeginThread();而这个线程我没有用new、malloc等在堆上分配内存,为了测试,我就while(1)&;(虽然在现实中不可能这样做,但也没有什么恶果,呵呵..)。那么这个线程就不会返回了。这个时候我调试运行,点击按钮启动线程,接着关闭应用程序(即关闭主线程),我没有在程序的任何地方加TerminateThread()或AfxEndThread(),即没有作任何处理,程序能够正常退出,没有警告,没有报错,但是出现了内存泄露,几条内存泄露信息,有一条还有100多字节。请问大家怎么解释?
嗯,我可以证实确实是这样的。
output出来这一坨:
Detected&memory&leaks!
Dumping&objects&-&
thrdcore.cpp(166)&:&{75}&client&block&at&0x00C026A0,&subtype&0,&108&bytes&long.
a&CWinThread&object&at&$00C026A0,&108&bytes&long
Object&dump&complete.
The&thread&0xC50&has&exited&with&code&0&(0x0).
跟到代码里看,原来是这样:
CWinThread*&AFXAPI&AfxBeginThread(AFX_THREADPROC&pfnThreadProc,&LPVOID&pParam,
int&nPriority,&UINT&nStackSize,&DWORD&dwCreateFlags,
LPSECURITY_ATTRIBUTES&lpSecurityAttrs)
#ifndef&_MT
pfnThreadP
lpSecurityA
return&NULL;
ASSERT(pfnThreadProc&!=&NULL);
CWinThread*&pThread&=&DEBUG_NEW&CWinThread(pfnThreadProc,&pParam);//&166行
ASSERT_VALID(pThread);
if&(!pThread-&CreateThread(dwCreateFlags|CREATE_SUSPENDED,&nStackSize,
lpSecurityAttrs))
pThread-&Delete();
return&NULL;
VERIFY(pThread-&SetThreadPriority(nPriority));
if&(!(dwCreateFlags&&&CREATE_SUSPENDED))
VERIFY(pThread-&ResumeThread()&!=&(DWORD)-1);
#endif&//!_MT)
原来是DEBUG_NEW的pThread没有释放,赫赫。
看来线程还是应该安全退出的,这个泄露确实只有lz那样的细心人才会发现。
用waitfor...当然是最好不过了。
Lz的Ls说的问题,如果不想用waitfor...,可以这样,AfxBeginThread()有个返回值,好像是CWinThread*类型,赋给某个变量m_pThread记录下来,对话框析构的时候,先TerminateThread()外部结束,然后delete&m_pThread就不会有内存泄漏了。不过最好把TerminateThread和delete放在try{}catch(...){}里面,这样即便是那个线程结束也不会出错……
Lz的Ls?赫赫,不会是老师吧。
嗯,楼上说的也有道理。不过最好还是wait,我认为。
terminatethread始终是在迫不得已的情况下才调用的,terminatethread后,被terminate的线程的heap和stack都不会自动释放,同样,线程所申请的操作系统资源也得不到释放,最危险还是像criticalsection、event之类的东西,进入后不能自动退出,这可是会导致死锁的,所以terminatethread请三思而后行。
还是设定事件对象来跟主线程进行通信,然后用waitfor...让辅助线程确定是否退出。
当主线程退出时要释放&m_pThread所指的线程对象,执行delete&&m_pT之前让主线程检测一下辅助线程是退出,当正常退出后再delete&&m_pT
不要强行用一个线程去终止别的线程,线程终止的最好方式是函数的正常退出,即执行return
w_anthony()的这种作法我已经做过了,但还是有内存的泄露,不信试试看!
dadi0189(流年似水......)所说确实有道理!~但你不的不承认一个事实:有的线程干的活比较多,你说通过事件的方式让辅助线程马上完成,立即return,举个例子:辅助线程调用一个控件里的函数,这个函数执行5秒钟才返回,它后面的一条语句才是等待主线程设置的事件对象(WaitForSingleEvent()),你总不可能在这个控件里的那个函数里加WaitForSingleEvent()吧?而在这个时候你关闭了应用程序(即关闭主线程),那么主线程会杀死辅助线程,造成资源的泄露!即使你在这个主线程的析构函数里激活辅助线程的WaitForSingleEvent()等待的事件,但已经说了,辅助线程里的一个函数还没有执行,那WaitForSingleEvent()能等到这个事件吗?所以这个时候还是主线程强行关闭辅助现成,造成资源泄露!!至于用TerminateThread(),那当然
是In&Vain,因为辅助线程没有执行完,这样还是强行终止啊!这个问题?
w_anthony()的这种作法我已经做过了,但还是有内存的泄露,不信试试看!?
拜托,我记得以前这样是不会有内存泄露的。今天听你说了,我特地又去试了一下,还是没有内存泄露。你怎么写的?要不要我发一份代码给你?
dadi0189(流年似水......)所说确实有道理!~但你不的不承认一个事实:有的线程干的活比较多,你说通过事件的方式让辅助线程马上完成,立即return,举个例子:辅助线程调用一个控件里的函数,这个函数执行5秒钟才返回,它后面的一条语句才是等待主线程设置的事件对象(WaitForSingleEvent()),你总不可能在这个控件里的那个函数里加WaitForSingleEvent()吧?而在这个时候你关闭了应用程序(即关闭主线程),那么主线程会杀死辅助线程,造成资源的泄露!即使你在这个主线程的析构函数里激活辅助线程的WaitForSingleEvent()等待的事件,但已经说了,辅助线程里的一个函数还没有执行,那WaitForSingleEvent()能等到这个事件吗?所以这个时候还是主线程强行关闭辅助现成,造成资源泄露!!至于用TerminateThread(),那当然
是In&Vain,因为辅助线程没有执行完,这样还是强行终止啊!这个问题?
=====================================
老兄,你说得有道理,但你主线程将要退出时应该检测一下辅助线程是否已正常退出了,要隔一小段时间反复检测直至线程已退出。辅助线程里如果调用了阻塞函数,就为把阻塞函数设置一个超时值,一般阻塞调用都提供这个参数,这样函数就在规定的时间里返回了,主线程检测到了就退出。
这个问题很好解决
设置一个主线程和辅助线程都可以看得见得BOOL变量,主线程退出事件发生时将这个BOOL变量置为TRUE,而辅助线程里面执行一点就检查一下这个值是否为TRUE,TRUE的时候就不要做后面的事情了,然后退出。主线程一直等待到子线程退出后再退出。
我每次都是这样做的,没有出现过内存泄露等问题。
但你主线程将要退出时应该检测一下辅助线程是否已正常退出了,要隔一小段时间反复检测直至线程已退出。辅助线程里如果调用了阻塞函数,就为把阻塞函数设置一个超时值,一般阻塞调用都提供这个参数,这样函数就在规定的时间里返回了,主线程检测到了就退出。
=====================================================================================
老兄,就是因为调用了阻塞函数,而且是人家已经写好的控件里的成员函数,就是这个问题吗?这个函数没有结束(要10秒钟才返回),辅助线程当然就没有退出?要是等到规定的10秒才结束辅助线程,怎么可能呢?主线程关闭了,也就杀死了辅助线程,哪还等10秒啊?就是因为这个线程是主线程强行杀死的,所以才造成泄露啊,老兄.
已经发过去了,csdn的短消息提示实在太烂……虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在。所以了解原理很重要。
这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled设置的使用。
本文假设你已经比较熟悉Obj-C的内存管理机制。
实验的开发环境:XCode 4.5.2
1、运行Demo。
先下载一个实现准备好的内存泄露的Demo吧:
下载下来,打开运行,程序是一个寿司的列表,列出各种寿司卷。试着选择里面的几行,应该是选第二行的时候就崩溃了。崩溃截图:
在崩溃的地方断住了,知道crash的地方了,但是不知道具体crash的原因。
2、设置NSZombieEnabled
这是一个 “EXC_BAD_ACCESS”错误。我们打开XCode的选项:“NSZombieEnabled”
。在crash时可能会给你更多的一些提示信息。
设置步骤:1
2:勾上红色框里的
运行,按刚才的操作选中其中的cell。再次crash,这次在output窗口会看到多了一项错误信息:
13:22:08.911 PropMemFun[] *** -[CFString respondsToSelector:]: message sent to deallocated instance 0x713ebc0
大概意思是:向已释放的内存发送消息。也就是说使用了已释放的内存,在C语言相当于使用了“野指针”
看了下crash的这个语句,sushiString应该是没问题的,它是从stringWithFormat初始化出来的。那就是_lastSushiSelected的问题。
_lastSushiSelected指向了sushiString,sushiString是一个autorelease变量。&在第二次点击时,使用的是sushiString已经被释放,所以crash了。那为_lastSushiSelected保留一下,就可以用了。代码修改如下:
&span&style=&font-size:14&&&&&&_lastSushiSelected&=&[sushiString&retain];&&&/span&&&
运行,这时候不崩溃。
3、分析内存泄露(shift+command+b)
app不crash了,那看看有没有内存泄露。用XCode的Analyze就能分析到哪里有内存泄露
分析之后可以看到:
这里提示alertView没被释放,有内存泄露,那我们释放
& &&[alertView release];
再分析,这个问题解决了。
4、使用Instruments的leaks工具
分析内存泄露不能把所有的内存泄露查出来,有的内存泄露是在运行时,用户操作时才产生的。那就需要用到Instruments了。
按上面操作,build成功后跳出Instruments工具,选择Leaks选项,这时候寿司程序也运行起来了,选中list中的项,拖动等操作后,工具显示效果如下:
大家可能都能猜到,红色的柱子表示内存泄露了。怎么通过这个工具看到在哪泄露了呢?
先在工具栏按下红色的圆形按钮,把工具监视内存的活动停下来。选择Leak,然后点中间十字交叉那,选择Call Tree.
这时候左下角的Call Tree的可选项可以选了。选中Invert Call Tree 和Hide System Libraries,显示如下:
这时候内存泄露的具体代码找到了,在右边的红色框框里指定了哪个方法出现了内存泄露。
你只要在这些方法上双击,就会跳转到具体的代码,哈哈,是不是很方便。
这里应该是提示100%内存会泄露。
6、解决内存泄露问题
问题找到了,那就解决吧
关于:tableView:didSelectRowAtIndexPath ,分析下它的内存过程:
sushiString变量通过autorelease创建,它的引用计数是1.& &这行代码使得引用计数增加到2,&_lastSushiSelected = [sushiString
retain];这个方法结束时,sushiString的autorelease生效了,这个变量的引用计数减少为1当再次执行tableView:didSelectRowAtIndexPath这个方法时,_lastSushiSelected被赋值了新指针,老的_lastSushiSelected的引用计数还是1,没有被释放,产生了内存泄露。
怎么解决呢?
在_lastSushiSelected&= [sushiString&retain];之前把原来的release就ok了:
[_lastSushiSelected&release];&&&&&&_lastSushiSelected&=&[sushiString&retain];&&
关于:tableView:cellForRowAtIndexPath
这个比较明显,sushiString被alloc和init之后就没有释放,可以用stringWithFormat来调用autorelease,代码如下:
NSString&*sushiString&=&[NSString&stringWithFormat:@&%d:&%@&,&indexPath.row,&sushiName];&&
好了,泄露都fix了,再用工具分析看看,这时候你再点,再拖,再怎么操作,都没有内存泄露了。表明内存泄露被堵住了。
这是本文修复好的app代码:
本文参考:
本文遵循“”创作公用协议
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:24059次
排名:千里之外
原创:32篇
转载:17篇
评论:10条
(18)(27)(4)}

我要回帖

更多关于 如何解决内存泄露 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信