美文网首页
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) 做了什么?

    准备工作 如果正常打印不请求调用流程是很难看到具体调用栈的,那就先让它crash,然后再去查看调用栈。 我们知道%...

  • _ _block

    _ _block测试 __block int ta2 =10; NSLog(@"ta3:---初始化时--...

  • iOS NSLog 本地化并邮件发送

    若在测试的时候,想得到测试机的 NSLog 日志,怎么得到呢,答案是很简单,将 NSLog 输出的内容存放在本地中...

  • 无标题文章

    OC基础语法 //整型 NSIntegera =10; //NSLog是OC里面的打印函数 NSLog(@"a =...

  • iOS培训总结

    一:OC基础语法1 //整型 NSInteger a =10; //NSLog是OC里面的打印函数 NSLog(@...

  • nslog重定义

    1、nslog重定义 优点:可以自定义打印样式,真机测试,内容过长的时候不会被截断 缺点:打印速度比nslog慢 ...

  • iOS GCD的快速迭代

    -(void)forDemo{//同步for(NSIntegeri =0; i<10; i++) {NSLog(@...

  • oc基本语法

    // oc基本语法 // 整形 NSInteger a = 10; // NSLog是oc里面的...

  • 获取APP中的NSLog日志

    本文是< > 第十五篇学习笔记. iOS10之前获取 NSLog 的日志 NSLog 其实就是一个 C 函数,函数...

  • Xcode控制台真机调试没有输出信息

    iOS10真机调试的话,会屏蔽掉NSLog

网友评论

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

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