Address Sanitizer 初探

前言

文中分享都基于自己的demo,完全模拟事发场景。

起因

前段时间,频繁收到不少QA童鞋报的crash。操作步骤各不相同,崩溃栈也没一个一样的,大致如下:

崩溃1

崩溃2

崩溃3

酱紫的崩溃,反正我看着是挺绝望的。。

感觉身体被掏空

完全是毫无头绪啊~~~

问题进展

挂了四五天的bug,期间经过不懈的努力,最后找到大致的复现规律了。在组内大腿的建议下,第一次使用起Address Sanitizer。

打开Address Sanitizer。run起来后,按照之前的复现步骤,居然一下就断住了。

捕获异常

显然,这是访问一个已经释放了的指针,的确是有问题。

但是。 这会跟之前的崩溃是一个原因么?

【PS:alloc和dealloc的地方,是继承的引擎库,没有代码权限,无法直接修改验证】

反正其他方式也没有进展,就当这个就是问题原因吧,那么继续分析下这样的操作之后,会发生什么事。

原因定位

搞个新项目,在vc的touchBegin中,加入如下代码

unsigned int size = 8; // size = 8,比较容易命中。
    buffer = malloc(size);
    snprintf(buffer, size, "Hello!");
    NSLog(@"%p, %s", buffer, buffer);
    free(buffer);
    
    // memory history <#expression#>
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 在未来的某个时机,改变该指针的值
        snprintf(buffer, size, "Hello!");
    });

这个与刚刚捕获到的异常,同样的是use-after-free。

run起来,碰了下viewController,咦,没崩?

弄啥嘞

再点了两下看看。

Boom~

特喵,再打开,再点! Boom~~

我不信,我点、我点、我点点点! Boom~~


导出crashLog,符号化之~


果然,几次崩溃完全不一样,全都在系统库中。

问题剖析

到这里,基本上定位到问题原因了。但是,为什么会乱蹦呢?

不弄清楚,不能忍!

打开刚刚新建的项目,搞俩断点

run ---> touch

走到断点A。同时控制台输出Log

2017-06-22 16:02:41.993918+0800 WWDC_Demo[9323:2875577] 0x148e512c0, Hello!

copy 上面的内存地址0x148e512c0。 cmd+shift+M,进入到View Memory界面,输入刚刚copy的内存地址。

查看内存

这时候能看到,右侧Hello! 这是刚代码中给buffer赋的值。

代码继续往下走,走过free(buffer).

再次cmd+shift+M,进入到View Memory界面,输入刚刚copy的内存地址。


友情提醒

注意,这时候不能直接点击右侧的树状结构中,之前生成的内存。那个不会实时更新,显示的是当时的内存内容。

每次打开ViewMemory,右侧会出现对应的树状结构

回到原来的话题,这时候发现,内存块的值,已经不再是Hello!

原来buffer的内存地址,值已经改变

纳尼?值变了?

咱们刚的代码中,明明只是free,释放了这块内存地址呀,并没有改变他的值。

难道说,刚刚free之后,马上就有其他地方申请到了这块内存地址,并修改了?


再次验证,修改代码中,malloc的size为1028。重新来一次之前的步骤。发现free后值依然是Hello! 。 也就是那块内存地址还没被申请,同样的,之后的操作也不会崩溃。

断点A、B均如此
再次提醒

修改size为1028,并不一定内存地址free后就不会再被重新申请了,只是概率较低。所以即使再被重新申请了,别慌,再来一次。~

另外,一旦被重新申请,那么程序继续跑下去,必然会导致崩溃在莫名其妙的地方。
反之,在断点B之前,还没有被重新申请,则不会崩溃。

结论

通过C语言,释放内存地址后,再操作内存区域。【oc是c的进一步封装,alloc和dealloc应该都有保护代码,操作基本都会马上崩溃】

  • 如果此时这块内存区域尚未被申请,还不会有问题。
  • 假如此时这块内存区域已经被申请,修改后,并不一定会马上出问题,待申请方重新使用的时候,就有可能崩溃。

当然,不管以上哪一种情况,Address Sanitizer都能捕获到。

Address Sanitizer原理简述

  • 在申请的内存地址两侧插入对应的redzone ==> 检测Overflow
  • 延迟已被free的堆空间的重用 ==> 检测Use-after-free
  • 访问某内存时,会检查其对应的shadow memory的state。
  • 管理shadow memory,同时保证shadow空间不被使用

PS:shadow memory --- 影子内存,每8个字节的内存会映射8位(1字节)的影子内存,用于表示对应内存的状态。
当检测到某块内存对应的shadow memory为0时,说明这块内存是OK,可使用的,反之,则捕获异常。


以上,如有描述不当,或者理解不对的地方,欢迎指出~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容