版权声明:本文为博主原创文章,未经博主允许不得转载。

我们做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

解决EXC_BAD_ACCESS错误的一种方法--NSZombieEnabled相关推荐

  1. 解决ms_cannot_allocmem错误的两种方法

    在mapgis插入光栅图件或者在图像分析数据转换成MSI格式时经常会出现ms_cannot_allocmem错误,如下图所示. 解决这一错误有两个方法: 1.把要插入或者转换的图片格式转换成另外一种图 ...

  2. 解决vimdiff ‘E97: Cannot create diffs‘错误的一种方法

    解决vimdiff 'E97: Cannot create diffs'错误的一种方法 | 赛因拔都 [ XBATU.COM ]http://www.xbatu.com/node/19 最近在新环境下 ...

  3. Android电视kodi安装失败,电视提示“解析包出现错误” ?四种方法教你轻松解决...

    原标题:电视提示"解析包出现错误" ?四种方法教你轻松解决 日常生活中,我们经常会遇到智能电视提示:解析包时出现错误.遇到这样的问题,不要抓狂,小智教你轻松解决. 首先,我们要清楚 ...

  4. 解决Navicat for MySQL 1045错误的三种方法

    解决Navicat for MySQL 1045错误的三种方法 Navicat连接MySQL数据库时难免会遇到1045错误,主要是因为用户输入的用户名或密码错误被拒绝访问,如果不想重装,需要找回密码或 ...

  5. Win11的两个实用技巧系列之解决dns异常的三种方法、win10/win11卡顿的三种解决办法

    电脑dns异常怎么修复win10? Win10解决dns异常的三种方法 电脑dns异常怎么修复win10?最近有很多win10用户遇到dns配置错误的问题,这让用户非常苦恼,下面我们就来看看Win10 ...

  6. vue开发环境和生产环境里面解决跨域的几种方法

    vue开发环境和生产环境里面解决跨域的几种方法 参考文章: (1)vue开发环境和生产环境里面解决跨域的几种方法 (2)https://www.cnblogs.com/pass245939319/p/ ...

  7. python安装错80072ee2_Windows10解决更新错误80072ee2的新方法

    最近看到很多用户都在反映Win10更新出现错误代码0x80072ee2的情况,经常导致补丁和应用无法更新,官方解释说,这种情况通常是由于电脑上某个程序阻止Windows更新和商店正常联网所致,那我们就 ...

  8. 修复Microsoft Edge上“无法到达此页面”错误的5种方法

    这里有五种方法来修复Microsoft Edge的"无法到达此页面"错误,以防你曾经在浏览器上遇到过这个错误. 尽管Edge是仅次于Chrome的第二大流行浏览器,但它也有一些故障 ...

  9. 避免问答机器人输出语法错误的一种方法

    >存在的问题 使用LSTM搭建问答(QA)机器人,训练语料集2000组对话,训练了300轮,测试精准度为98%.模型方框图如下: 实测聊天发现,当输入的问题与训练集中一样时,模型输出很好,当输入 ...

最新文章

  1. python反射和高阶内置方法
  2. 给大家推荐对Redis分析讲解比较详细的大牛
  3. Spring IOC容器-注解的方式【更简化】
  4. 关于ics lab8 performance中的rotate
  5. C++ 操作sqlite
  6. 猴子排序的期望复杂度推导(雾)
  7. 玩转c语言——c语言小游戏 迷宫小游戏(附源码)
  8. 图解TCPIP---第二章
  9. WPF子线程更新UI
  10. Java实现数字大写
  11. BurpSuite工具-HTTP协议详解部分(不懂就查系列)
  12. android后台流量限制,手机流量控制!安卓手机控制流量设置小技巧
  13. kali配置静态IP地址
  14. 谷歌 浏览器二维码显示异常,形成的二维码无法被扫描
  15. 由建站学linux---第13课 域名重定向
  16. http拨测是什么意思_网络性能拨测-网络传输速度体验检测系统有哪些指标?
  17. 大数据剖析热点新闻:996、巴黎圣母院、奔驰维权为什么成为本周热搜
  18. Activity的相关知识(一)
  19. python编写淘宝秒杀脚本
  20. CC2540驱动安装: CC2540 USB dongle COM port driver

热门文章

  1. Streaming API
  2. java props_spring:使用prop标签为Java持久属性集注入值
  3. eclipse和idea代码通用吗_25个JavaScript代码简写技巧(下篇)
  4. ajax获取301,PHP获取301重定向页面跳转后真实URL地址
  5. maple 2018 窗口关闭提示乱码_iPhone最废柴却无法关闭的俩功能,我终于屏蔽了!...
  6. ibatis mysql_mysql +ibatis
  7. 鸿蒙OS电脑体验,华为鸿蒙OS体验抢先曝光!有多个更新版本,界面和安卓完全不同...
  8. c语言最小点对问题_7.4 图的连通性问题
  9. 使用该JavaBean可以将数据在JSP页面中以表格的形式显示出来 并具有动态排序 动态生成查询 自动分页功能
  10. 【BZOJ1188】分裂游戏,博弈