Xcode特性Address Sanitizer,对比僵尸对象

卓同学的文章Xcode7中你一定要知道的炸裂调试神技,介绍Xcode7中新增了AddressSanitizer工具可以捕获EXC_BAD_ACCESS。然而Xcode中不是已经有了Zombie了么?怎么又出来了一个Address Sanitizer,他们有什么区别呢?

AddressSanitizer VS Zombie

原理

  1. zombie
    zombie的原理是用生成僵尸对象来替换dealloc的实现,当对象引用计数为0的时候,将需要dealloc的对象转化为僵尸对象。如果之后再给这个僵尸对象发消息,则抛出异常,并打印出相应的信息,调试者可以很轻松的找到异常发生位置。
  2. AddressSanitizer
    AddressSanitizer的原理是当程序创建变量分配一段内存时,将此内存后面的一段内存也冻结住,标识为中毒内存。如图所示,黄色是变量所占内存,紫色是冻结的中毒内存。

 当程序访问到中毒内存时(越界访问),就会抛出异常,并打印出相应log信息。调试者可以根据中断位置和的log信息,识别bug。如果变量释放了,变量所占的内存也会标识为中毒内存,这时候访问这段内存同样会抛出异常(访问已经释放的对象)。

1、Malloc Scribble ,其官方解释如下:申请内存 alloc 时在内存上填0xAA,释放内存 dealloc 在内存上填 0x55

Zombie Objects,其官方解释如下:一个对象已经解除了它的引用,已经被释放掉,但是此时仍然是可以接受消息,这个对象就叫做Zombie Objects(僵尸对象)。这种方案的重点就是将释放的对象,全都转为僵尸对象

适用性

了解原理之后我们可以大概猜到Zombie和AddressSanitizer的适用性,不过一切还得以实验结果为准:

 实验后发现AddressSanitizer比Zombie拥有更强大的捕获能力,特别是在malloc对象和内存越界方面,zombie几乎无能为力。如果在debug的时候无法捕获异常,上线之后crash log中概率性的EXC_BAD_ACCESS简直是一种灾难。

缺陷

上面研究发现AddressSanitizer比zombie更有优势,那么AddressSanitizer有什么缺陷呢?

  1. AddressSanitizer可能会没有log,不过会在访问中毒内存的代码处断住,这倒是对debug影响不大
  2. 使用AddressSanitizer除了分配对象的内存之外,还需要额外的内存,这会导致App内存大量增加,用起来有可能会比较卡

虽然AddressSanitizer有一些缺陷,但是总的来说AddressSanitizer还是一个非常好用的debug工具。

AddressSanitizer使用

在了解AddressSanitizer的功能之后,我们来看看AddressSanitizer用。
AddressSanitizer的使用其实非常简单,在Xcode上方选择设备的地方,点击工程名字,选择Edit Scheme.

 在Diagnostics中选中enable address sanitizer即可。

AddressSanitizer开启之后,在debug过程中,如果遇到EXC_BAD_ACCESS的问题,Xcode会自动中断,抛出异常

野指针分析方法(Enable Malloc Scribble)

因为野指针的原因发生崩溃是常常出现的事,而且比较随机。

对象释放后只有出现被随机填入的数据是不可访问的时候才会必现Crash。

这个地方我们可以做一下手脚,把这一随机的过程变成不随机的过程。对象释放后在内存上填上不可访问的数据,其实这种技术其实一直都有,xcode的Enable Scribble(乱涂)就是这个作用。会在对象释放后随机填写一些数据, 然后在访问这个内存后就会复现崩溃

  其他compiler flags 

实际AddressSanitizer很早以前就有了,只是没在Xcode中集成而已。除了AddressSanitizer还有很多其他的compiler flags,undefined-trap就是其中的一种。undefined-trap的功能也非常强大,它可以检测出程序中的不明确行为,如数据溢出等。

下面我们以undefined-trap举例,看看怎么用其他的compiler flags:

在Build Settings中的Custom Compiler Flags下为other C Flags添加-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error

 完成undefined-trap的设置之后,当程序的数据发生溢出行为时,系统就会抛出异常。

End

经过ARC的洗礼之后,普通的访问释放对象产生的EXC_BAD_ACCESS已经大量减少了,现在出现的EXC_BAD_ACCESS有很大一部分来自malloc的对象或者越界访问。简单的敌人已经被干掉,剩下的都是难缠的对手了。还好Apple给我们升级了装备,以后遇到EXC_BAD_ACCESS应该不用那么心惊胆战了吧?

最后安利下: Xcode7中你一定要知道的炸裂调试神技

Address Sanitizer原理介绍

Scribble和Zombie原理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值