问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

ios leaks afnetworking3.0多处内存泄露怎么回事

发布网友 发布时间:2022-05-03 20:09

我来回答

2个回答

懂视网 时间:2022-05-04 00:31

我们做iOS 程序开发时经常用遇到 EXC_BAD_ACCESS 错误导致 Crash,出现这种错误时一般 Xcode 不会给我们太多的信息来定位错误来源,只是在应用 Delegate 上留下像 Thread 1: Program received signal:EXC_BAD_ACCESS ,让问题无从找起。 比如你对已释放的对

我们做iOS 程序开发时经常用遇到 EXC_BAD_ACCESS 错误导致 Crash,出现这种错误时一般 Xcode 不会给我们太多的信息来定位错误来源,只是在应用 Delegate 上留下像Thread 1: Program received signal:"EXC_BAD_ACCESS",让问题无从找起。

比如你对已释放的对象发送消息时就会出现,EXC_BAD_ACCESS,再如release 的对象再 release,release 那些autorelease 的对象等也会报这样的错。默认设置下 Xcode 不会给你定位具体是哪一行代码,不该去使用已释放的对象,或者release 用错了。

比如 UIViewController 子类中这样的代码:

[cpp] view plaincopyprint?

  1. static NSMutableArray*array;
  2. -(void)viewDidLoad
  3. {
  4. [superviewDidLoad];
  5. array= [[NSMutableArray alloc]initWithCapacity:5];
  6. [array release];//释放掉该数组
  7. }
  8. - (void)viewWillAppear:(BOOL)animated{
  9. [array addObject:@"Hello"];//使用释放掉的数组
  10. }


上面的代码就会出现EXC_BAD_ACCESS 错误,但我执行时 Xcode 一出错却是定位在我在 AppDelegate 的 application:didFinishLaunchingWithOptions: 方法上的某行了,如果代码量多了,要查找具体问题非常难,但凭经验了。

不过NSZombieEnabled 环境变量可以帮我们的忙,就是当设置NSZombieEnabled环境变量后,一个对象销毁时会被转化为_NSZombie,设置NSZombieEnabled后,当你向一个已经释放的对象发送消息,这个对象就不会向之前那样Crash或者产生一个难以理解的行为,而是放出一个错误消息,然后以一种可预测的可以产生debug断点的方式消失, 因此我们就可以找到具体或者大概是哪个对象被错误的释放了。

Xcode 设置了NSZombieEnabled 之后,Xcode 会明确定位在行[array addObject:@"Hello"],然后控制台下报的错误信息是:

*** -[__NSArray addObject:]:message sent to deallocated instance 0x6557370

如何设置 NSZombieEnabled 呢,在 Xcode3 Xcode4 下设置不一样,Xcode4 下设置很简单。
Xcode3 NSZombieEnabled 设置方法如下:

1. 在XCode左边那个Groups& Files栏中找到Executables,双击其中的一项,或者右键Get Info;
2. 切换到Arguments
3. 这里一共有两个框,在下面那个Variables to be set in theenvironment:点+号添加一项,Name里填NSZombieEnabled,Value填Yes,要保证前面的钩是选中的。

Xcode4 下设置 NSZombieEnabled 的方法:

你可以点击 Xcode4 菜单 Product -> Edit Scheme-> Arguments, 然后将点击”加号”, 将 NSZombieEnabled 参数加到Environment Variables 窗口中, 后面的数值写上 ”YES”.

或者在 Xcode4 菜单 Product -> EditScheme -> Diagnostics 设置窗口中直接勾上Enable ZombieObjects 即可,Xcode 可用 cmd+shift+< 进到这个窗口。

Xcode4 已经考虑到了现在的要求,所以提供了更便捷的设置的方式,你也可以在这个窗口中设置其他一些参数,你肯定能由此获得更多的帮助信息。

另外再说一下,如果没有为 Xcode 设置 NSZombieEnable,像下面的代码或许可以正确执行,打印出你所期望的结果“Hello”

[cpp] view plaincopyprint?

  1. static NSMutableArray*array;
  2. -(void)viewDidLoad
  3. {
  4. [super viewDidLoad];
  5. array= [[NSMutableArray alloc]initWithCapacity:5];
  6. [array release];
  7. [array addObject:@"Hello"];//之所以不会crash,是在于事件周期未完,内存回收机制还没有执行,没有真正的回收掉array的对象内存。
  8. NSLog(@"%@",[array objectAtIndex:0]);
  9. }



但是一旦加上了NSZombieEnable 设置,上面的代码行 [array addObject:@"Hello"] 也将无法投机取巧了,同样会得到错误提示:

*** -[__NSArrayM addObject:]:message sent to deallocated instance 0x6557370

即使该array 所指向的内存还是原来的数据也不能逃脱掉 NSZombieEnable 的法眼。也就是之所以未设置 NSZombieEnable 时上面代码能得到正确结果,是因为,虽然 [array release] 是标记为释放掉该内存块,但是后面使用 array 时,因为该指针指向的内存数据未被覆盖,所以未出错,这和C++ 的指针 delete 后的效果是一样的。


  1. CocoaDev,个人觉得讲Cocoa技术十分专业的网站之一,下面的链接详细讲了讲NSZombieEnable的原理。http://www.cocoadev.com/index.pl?NSZombieEnabled
  2. 苹果官方的Mac OS X Debugging Magic,详细讲述了最为一个高级苹果程序员应该具备的调试技巧 http://developer.apple.com/library/mac/#technotes/tn2004/tn2124.html
  3. 其实还可以在Instruments中开启NSZombie选项,这样就可以在Instruments中直接查看crash时候的callstack了:http://www.markj.net/iphone-memory-debug-nszombie/

最后提醒NSZombieEnabled只能在调试的时候使用,千万不要忘记在产品发布的时候去掉,因为NSZombieEnabled不会真正去释放dealloc对象的内存,一直开启后果可想而知,自重!

http://unmi.cc/nszombieenabled-locate-exc_bad_access-error,来自 隔叶黄莺 Unmi Blog

热心网友 时间:2022-05-03 21:39

1、运行Demo。
先下载一个实现准备好的内存泄露的Demo吧:leak app
下载下来,打开运行,程序是一个寿司的列表,列出各种寿司卷。试着选择里面的几行,应该是选第二行的时候就崩溃了。崩溃截图:

在崩溃的地方断住了,知道crash的地方了,但是不知道具体crash的原因。

2、设置NSZombieEnabled
这是一个 “EXC_BAD_ACCESS”错误。我们打开XCode的选项:“NSZombieEnabled” 。在crash时可能会给你更多的一些提示信息。
设置步骤:1

2:勾上红色框里的

运行,按刚才的操作选中其中的cell。再次crash,这次在output窗口会看到多了一项错误信息:

2012-11-28 13:22:08.911 PropMemFun[2132:11303] *** -[CFString respondsToSelector:]: message sent to deallocated instance 0x713ebc0
大概意思是:向已释放的内存发送消息。也就是说使用了已释放的内存,在C语言相当于使用了“野指针”

看了下crash的这个语句,sushiString应该是没问题的,它是从stringWithFormat初始化出来的。那就是_lastSushiSelected的问题。
_lastSushiSelected指向了sushiString,sushiString是一个autorelease变量。 在第二次点击时,使用的是sushiString已经被释放,所以crash了。那为_lastSushiSelected保留一下,就可以用了。代码修改如下:

[cpp] view plaincopy
<span style="font-size: 14px;"> _lastSushiSelected = [sushiString retain];
</span>
[cpp] view plain copy
<span style="font-size:14px;"> _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了:

[cpp] view plaincopy
<span style="font-size: 14px;"> [_lastSushiSelected release];
_lastSushiSelected = [sushiString retain];</span>
[cpp] view plain copy
<span style="font-size:14px;"> [_lastSushiSelected release];
_lastSushiSelected = [sushiString retain];</span>
关于:tableView:cellForRowAtIndexPath
这个比较明显,sushiString被alloc和init之后就没有释放,可以用stringWithFormat来调用autorelease,代码如下:

[cpp] view plaincopy
<span style="font-size: 14px;">NSString *sushiString = [NSString stringWithFormat:@"%d: %@", indexPath.row, sushiName];</span>
[cpp] view plain copy
<span style="font-size:14px;">NSString *sushiString = [NSString stringWithFormat:@"%d: %@", indexPath.row, sushiName];</span>
好了,泄露都fix了,再用工具分析看看,这时候你再点,再拖,再怎么操作,都没有内存泄露了。表明内存泄露被堵住了。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
为什么打电话给别人,显示无法接通? 我给对方打电话时,他那边响一声后就提示无法接通是什么情况? iPhone 6Plus相机远距离无法对焦,得用力摇几下才恢复,过会又模糊,什么... iphone6plus。近拍清楚,远拍模糊,怎么回事?聚焦不了。 怎么办~ 廉锦枫《廉锦枫》——剧情分析 我想取个好听的英文名字,而且希望是有意义的`拜托了各位谢谢 不锈钢公司取名带匠字文化深厚的企业名称大全 带匠字的厂名 公司名字为什么不可以带匠字 我儿子刚上一年级老师给我发微信时表现不错我怎么和老师沟通 如何将一个有数值的字段的数据类型改为“自动编号”? access数据库id自动编号问题 数据表的设计视图中,带有主键的自动编号类型字段是否可以改成数字类型? access数据库自动编号字段出现重复数字?! 自动编号去可以改成数字类型吗?求原因 2010版ACCESS数据库中的自动编号ID如何才能修改 access查询向导如何更改数据类型,为什么我的总是自动变成数字类型,我想让他是文本类型 Access Denied. 出现错误,应该怎样解决!详细点! 如何为ContentProvider添加访问权限 android怎么在androidmanifest.xml文件中注册权限 为什么需要 android.permission.ACCESS android.permission.access_superuser在 manifest中未定义。 软件出现这个怎么设置,本人知道qq开始的 打包发布apk怎么解决android.permission.access 如何在服务器上连接access数据库 我开网站出现了You don&#39;t have permission to access &#47; on this server应该怎样设置?~~ Android权限添加了但是还是报错,求助各位 accesspermission 是做什么用的? 如何给eclipse里面添加权限啊? 如何在服务器资源管理器中添加access的连接? android service权限问题 使用了arc是不是就等于没有内存泄漏了 c语言代码出现,access violation,是怎么回事,请大家麻烦看看! 有谁知道电脑弹出这个Access violation at addr......窗口是什么意思 C语言程序调试时出现access violation 。。如下,求解。。 电脑经常出现access violation at address 00000000. 是什么意思,请电脑高手指教应该怎么办??/ 电脑一直弹出Access violation at address... 我一开机.就弹出“Access violation at address 00000000.Read of adress 00000000. 怎么回事,怎样修复 每次开机出现access violation at address 00000017 运行软件弹出access violation at address 软件可以打开,但是不完全,感觉打开一半一样 开机时弹出对话框access violation at address 032246f4 in module &#39;zehese.dll&#39;.read of address soildworks2018安装中出现access violation 哪位大牛能帮忙看下我的程序,调试过程中出现access violation错误 开机自动弹出access violation at address 00523CC9 in module &quot;RaUI.exe.…… 用APP启动游戏时出现ACCESS VIOLATION... 电脑弹出Access violation at address 0045C083 in module &#39;emsoft.exe&#39;.Read of 电脑弹出Access violation at address 00405CEC in midule &quot;登录.exe&quot;.Read of address 00000000. 求助:读取txt文件操作,遇到access violation错误 Access使用SQL如何分页,具体代码又是??? 请问C#三层LISTVIEW+ACCESS怎么做高效分页(三层里面LISTVIES+ACCESS高效分页怎么做) access 分页sql的问题