美文网首页
NSLog(@"测试%@",10) 做了什么?

NSLog(@"测试%@",10) 做了什么?

作者: 哦小小树 | 来源:发表于2020-04-27 11:56 被阅读0次
    准备工作

    如果正常打印不请求调用流程是很难看到具体调用栈的,那就先让它crash,然后再去查看调用栈。

    我们知道%@是用来接Objective-C对象类型的。如果用它来接收int类型就会crash。那我们就从这里入手。


    0x01 %d接收10的调用栈

    • 测试代码:
    int a = 10;
    NSLog(@"测试%@",a);
    
    • crash截图

      WeChat5d3773466930a21378cddf74cb3675d3.png
    • crash 分析

    调用栈分析

    (lldb) bt
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1)
      * frame #0: 0x00007fff50b52d93 libobjc.A.dylib`objc_opt_respondsToSelector + 13
        frame #1: 0x00007fff2593f4ea Foundation`_NSDescriptionWithStringProxyFunc + 41
        frame #2: 0x00007fff23dc69c7 CoreFoundation`__CFStringAppendFormatCore + 10935
        frame #3: 0x00007fff23dc8cf5 CoreFoundation`_CFStringCreateWithFormatAndArgumentsAux2 + 133
        frame #4: 0x00007fff51bc3e08 libsystem_trace.dylib`_os_log_impl_dynamic + 228
        frame #5: 0x00007fff51bc446b libsystem_trace.dylib`_os_log_with_args_impl + 562
        frame #6: 0x00007fff23e2085b CoreFoundation`_CFLogvEx3 + 235
        frame #7: 0x00007fff25924e40 Foundation`_NSLogv + 104
        frame #8: 0x00007fff25924ed8 Foundation`NSLog + 132
    
    

    通过调用栈我们可以发现,是因为访问了错误的地址address=0x1导致crash的。
    crash崩溃点可以发现:

    ->  0x7fff50b52d93 <+13>: movq   (%rcx), %rdx   
    

    汇编解析:
    rcx这个寄存器存放的是个地址,将这个地址中的内容取出放到rdx这个寄存器。

    打印寄存器

    lldb) register read
    General Purpose Registers:
           rax = 0x00007fff51fbad08
           rbx = 0x00007ffee180ef00
           rcx = 0x0000000000000001
           rdx = 0x00007fff80640e90  @"%@NSCONTEXT"
           rdi = 0x0000000000000001
    

    可以发现:
    rcx地址太小,根本不是个指针。故而我们也不可能从里面取到一个内容.


    0x02 %@ 接收string的调用栈

    • 测试代码
    NSLog(@"测试: %@",@"hello");
    
    • 符号断点截图:


      WeChatecc62b3d7e67cfcdf3d40e4534bbcb73.png
    WeChat9579ff19e721db31141b5cfe99f99bf6.png

    0x03 %@接收object的调用栈

    • 测试代码
    // self是一个控制器ViewController
    NSLog(@"测试: %@",self);
    
    • 符号断点截图


      WeChat22d2b7109294087c9713a7596d677242.png

    通过上图我们可以发现rcx是个指针,可以取到指针内容。
    由此发现在格式转换中%@在转换过程中是需要取入参对象的地址的。


    总结

    NSLog(@"测试%@",10) crash的原因:访问了错误的地址信息,应该去查找一个指针的,结果查看了一个常量。

    啰嗦的描述:
    在后续的内存操作中,会将 10做出些调整当成一个指针,然后去取它的内容,当发现取不出内容时自然出现问题。

    发散一下:
    如果创建一个对象,然后把这个对象的地址转为整型赋值是否可行?

    参考:
    苹果官方日志打印接收类型

    相关文章

      网友评论

          本文标题:NSLog(@"测试%@",10) 做了什么?

          本文链接:https://www.haomeiwen.com/subject/rstywhtx.html