V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
fffang
V2EX  ›  iDev

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

  •  
  •   fffang · 2020-12-07 11:54:36 +08:00 · 4396 次点击
    这是一个创建于 1431 天前的主题,其中的信息可能已经有所发展或是发生改变。

    image.png

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

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

    13 条回复    2020-12-10 19:09:43 +08:00
    Qusic
        1
    Qusic  
       2020-12-07 12:26:28 +08:00 via iPhone
    上一行,retain bl 过去访问了 0x20 这个无效的地址
    sunnywqf
        2
    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
        3
    fffang  
    OP
       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
        4
    fffang  
    OP
       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
        5
    sunnywqf  
       2020-12-08 13:02:51 +08:00
    @fffang 能给一个更完整的 demo 吗?
    arnoldxiao
        6
    arnoldxiao  
       2020-12-09 16:19:00 +08:00
    - (instancetype)new_initWithCoder:(NSCoder *)coder{
    self = [self new_initWithCoder:coder];
    return self;
    }
    fffang
        7
    fffang  
    OP
       2020-12-09 16:41:34 +08:00
    @arnoldxiao 这样是可以的,同理,把方法名中的 new 换掉也可以,直接 return 也可以,不过想知道为什么 self 经过原来的 init 方法会被 release 掉。
    arnoldxiao
        8
    arnoldxiao  
       2020-12-10 09:34:15 +08:00
    @fffang 不是被释放掉,你上一行执行初始化的返回实例没有赋值给 self,相当于 self 没有初始化
    onevcat
        9
    onevcat  
       2020-12-10 11:47:12 +08:00   ❤️ 1
    OC 的 naming convention 里有一条叫做,new 开头的方法返回的东西会被认为 retain count +1 。但是实际上你的代码里并没有 retain 它,所以在 ARC 的世界里,这部分内存会被 release 两次,你就挂了。

    记住,没搞清楚的情况下,别用 `new` 做方法或者属性的开头。同理还有 copy 啊之类的。
    calvincheung
        10
    calvincheung  
       2020-12-10 15:03:32 +08:00
    @onevcat 附议
    fffang
        11
    fffang  
    OP
       2020-12-10 16:49:58 +08:00
    @onevcat 感谢,了解了。不过我翻了 objc 源码也没发现哪个地方有这部分的实现,用 clang 转写成 c++也不会有 retain 之类的关键词。
    fffang
        12
    fffang  
    OP
       2020-12-10 18:58:29 +08:00
    其实我正是在寻找 objc 内部处理 prefix 为 new 的方法的实现才特意这么写的,不过导致崩溃确实是我没想到的。
    fffang
        13
    fffang  
    OP
       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 开头的方法到底做了什么呢?附上两个这两个仅仅方法名不同的汇编实现以供有兴趣的同学研究~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5661 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 03:09 · PVG 11:09 · LAX 19:09 · JFK 22:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.