这种 crash 算是崩溃在哪一行?

2020-12-07 11:54:36 +08:00
 fffang

比如这个,是执行 objc_retain 崩溃还是执行 ldr 崩溃的?

之所以问这个问题是我在 ldr 处打了断点,按道理说还没执行 ldr 。

4453 次点击
所在节点    iDev
13 条回复
Qusic
2020-12-07 12:26:28 +08:00
上一行,retain bl 过去访问了 0x20 这个无效的地址
sunnywqf
2020-12-07 12:54:13 +08:00
估计是 x0 里的对象已经被释放了:

(lldb) disassemble -n objc_retain
libobjc.A.dylib`objc_retain:
0x1c0aa7be0 <+0>: cbz x0, 0x1c0aa7c14 ; <+52>
0x1c0aa7be4 <+4>: tbnz x0, #0x3f, 0x1c0aa7c14 ; <+52>
0x1c0aa7be8 <+8>: ldr x8, [x0]
0x1c0aa7bec <+12>: and x8, x8, #0xffffffff8
0x1c0aa7bf0 <+16>: ldrb w8, [x8, #0x20] //////// 是在这里挂了, 加个断点看看
0x1c0aa7bf4 <+20>: tbz w8, #0x2, 0x1c0aa7c18 ; <+56>
0x1c0aa7bf8 <+24>: orr x8, xzr, #0x200000000000
fffang
2020-12-07 15:06:56 +08:00
@sunnywqf
为啥我在 hopper 里或 xcode 断点里看 objc_retain 是这样的

```
imp___stubs__objc_retain: // objc_retain
0000000100006548 nop ; CODE XREF=-[UIViewController new_initWithCoder:]+84
000000010000654c ldr x16, #_objc_retain_ptr ; _objc_retain
0000000100006550 br x16 ; _objc_retain
; endp
```
fffang
2020-12-07 15:31:32 +08:00
```
- (instancetype)new_initWithCoder:(NSCoder *)coder{
[self new_initWithCoder:coder];
return self;
}
```


@sunnywqf 原始代码就这些,就是 hook 了初始化方法。按照上述代码运行会崩溃,但是直接` [self new_initWithCoder:coder];`这样是不会崩溃的,有兴趣的话可以一起研究下。
sunnywqf
2020-12-08 13:02:51 +08:00
@fffang 能给一个更完整的 demo 吗?
arnoldxiao
2020-12-09 16:19:00 +08:00
- (instancetype)new_initWithCoder:(NSCoder *)coder{
self = [self new_initWithCoder:coder];
return self;
}
fffang
2020-12-09 16:41:34 +08:00
@arnoldxiao 这样是可以的,同理,把方法名中的 new 换掉也可以,直接 return 也可以,不过想知道为什么 self 经过原来的 init 方法会被 release 掉。
arnoldxiao
2020-12-10 09:34:15 +08:00
@fffang 不是被释放掉,你上一行执行初始化的返回实例没有赋值给 self,相当于 self 没有初始化
onevcat
2020-12-10 11:47:12 +08:00
OC 的 naming convention 里有一条叫做,new 开头的方法返回的东西会被认为 retain count +1 。但是实际上你的代码里并没有 retain 它,所以在 ARC 的世界里,这部分内存会被 release 两次,你就挂了。

记住,没搞清楚的情况下,别用 `new` 做方法或者属性的开头。同理还有 copy 啊之类的。
calvincheung
2020-12-10 15:03:32 +08:00
@onevcat 附议
fffang
2020-12-10 16:49:58 +08:00
@onevcat 感谢,了解了。不过我翻了 objc 源码也没发现哪个地方有这部分的实现,用 clang 转写成 c++也不会有 retain 之类的关键词。
fffang
2020-12-10 18:58:29 +08:00
其实我正是在寻找 objc 内部处理 prefix 为 new 的方法的实现才特意这么写的,不过导致崩溃确实是我没想到的。
fffang
2020-12-10 19:09:43 +08:00
InitWithCoder`-[UIViewController(hook) new_initWithCoder:]:
0x1043e1e60 <+0>: sub sp, sp, #0x40 ; =0x40
0x1043e1e64 <+4>: stp x29, x30, [sp, #0x30]
0x1043e1e68 <+8>: add x29, sp, #0x30 ; =0x30
0x1043e1e6c <+12>: stur x0, [x29, #-0x8]
0x1043e1e70 <+16>: stur x1, [x29, #-0x10]
0x1043e1e74 <+20>: add x8, sp, #0x18 ; =0x18
0x1043e1e78 <+24>: mov x9, #0x0
0x1043e1e7c <+28>: str x9, [sp, #0x18]
0x1043e1e80 <+32>: mov x0, x8
0x1043e1e84 <+36>: mov x1, x2
0x1043e1e88 <+40>: str x8, [sp, #0x10]
0x1043e1e8c <+44>: str x9, [sp, #0x8]
0x1043e1e90 <+48>: bl 0x1043e253c ; symbol stub for: objc_storeStrong
0x1043e1e94 <+52>: ldur x0, [x29, #-0x8]
0x1043e1e98 <+56>: ldr x2, [sp, #0x18]
0x1043e1e9c <+60>: adrp x8, 4
0x1043e1ea0 <+64>: add x8, x8, #0x4b8 ; =0x4b8
0x1043e1ea4 <+68>: ldr x1, [x8]
0x1043e1ea8 <+72>: bl 0x1043e2500 ; symbol stub for: objc_msgSend
0x1043e1eac <+76>: bl 0x1043e2518 ; symbol stub for: objc_release
-> 0x1043e1eb0 <+80>: ldur x0, [x29, #-0x8]
0x1043e1eb4 <+84>: bl 0x1043e2524 ; symbol stub for: objc_retain
0x1043e1eb8 <+88>: ldr x8, [sp, #0x10]
0x1043e1ebc <+92>: str x0, [sp]
0x1043e1ec0 <+96>: mov x0, x8
0x1043e1ec4 <+100>: ldr x9, [sp, #0x8]
0x1043e1ec8 <+104>: mov x1, x9
0x1043e1ecc <+108>: bl 0x1043e253c ; symbol stub for: objc_storeStrong
0x1043e1ed0 <+112>: ldr x0, [sp]
0x1043e1ed4 <+116>: ldp x29, x30, [sp, #0x30]
0x1043e1ed8 <+120>: add sp, sp, #0x40 ; =0x40
0x1043e1edc <+124>: ret



InitWithCoder`-[UIViewController(hook) abc_initWithCoder:]:
0x104ac1e60 <+0>: sub sp, sp, #0x40 ; =0x40
0x104ac1e64 <+4>: stp x29, x30, [sp, #0x30]
0x104ac1e68 <+8>: add x29, sp, #0x30 ; =0x30
0x104ac1e6c <+12>: stur x0, [x29, #-0x8]
0x104ac1e70 <+16>: stur x1, [x29, #-0x10]
0x104ac1e74 <+20>: add x8, sp, #0x18 ; =0x18
0x104ac1e78 <+24>: mov x9, #0x0
0x104ac1e7c <+28>: str x9, [sp, #0x18]
0x104ac1e80 <+32>: mov x0, x8
0x104ac1e84 <+36>: mov x1, x2
0x104ac1e88 <+40>: str x8, [sp, #0x10]
0x104ac1e8c <+44>: str x9, [sp, #0x8]
0x104ac1e90 <+48>: bl 0x104ac2530 ; symbol stub for: objc_storeStrong
0x104ac1e94 <+52>: ldur x0, [x29, #-0x8]
0x104ac1e98 <+56>: ldr x2, [sp, #0x18]
0x104ac1e9c <+60>: adrp x8, 4
0x104ac1ea0 <+64>: add x8, x8, #0x4b8 ; =0x4b8
0x104ac1ea4 <+68>: ldr x1, [x8]
0x104ac1ea8 <+72>: bl 0x104ac2500 ; symbol stub for: objc_msgSend
0x104ac1eac <+76>: mov x29, x29
0x104ac1eb0 <+80>: bl 0x104ac253c ; symbol stub for: objc_unsafeClaimAutoreleasedReturnValue
-> 0x104ac1eb4 <+84>: ldur x8, [x29, #-0x8]
0x104ac1eb8 <+88>: ldr x9, [sp, #0x10]
0x104ac1ebc <+92>: mov x0, x9
0x104ac1ec0 <+96>: ldr x10, [sp, #0x8]
0x104ac1ec4 <+100>: mov x1, x10
0x104ac1ec8 <+104>: str x8, [sp]
0x104ac1ecc <+108>: bl 0x104ac2530 ; symbol stub for: objc_storeStrong
0x104ac1ed0 <+112>: ldr x0, [sp]
0x104ac1ed4 <+116>: ldp x29, x30, [sp, #0x30]
0x104ac1ed8 <+120>: add sp, sp, #0x40 ; =0x40
0x104ac1edc <+124>: ret

以 new 开头的方法到底做了什么呢?附上两个这两个仅仅方法名不同的汇编实现以供有兴趣的同学研究~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/732874

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX