iOS底层分析-block(三)

1,357 阅读3分钟

这是我参与8月更文挑战的第30天,活动详情查看: 8月更文挑战

汇编分析block流程

在上一篇文章中我们分析了block的底层结构,接下里我们分析一下block的执行流程;

我们新建一个iOS工程,然后编写如下代码:

block的地方打上断点,然后运行项目,打开汇编界面:

在汇编代码中,我们定位到了objc_retainBlock这样一个符号;我们添加符号断点objc_retainBlock,继续执行代码:

发现接下来,将会调用_Block_copy,继续添加符号断点_Block_copy,向下执行代码:

发现_Block_copy来自于libsystem_blocks.dylib,同样的调用我们从objc的源码中也可以分析得到:

定位到_Block_copy之后,我们无法继续向下分析,因为libsystem_blocks没有开源;但是我们可以从libclosure的源码中找到_Block_copy的实现:

_Block_copy中,定义了一个结构体struct Block_layout *aBlock;,其结构如下:

  • 结构体中有个isa的成员变量,(指向栈block或者堆block)
  • flags标识码,里边可以存储一些数据信息;
  • invoke是调用函数;
  • descriptor相关描述信息(比如是否有有析构函数等等信息)

此时,我们打印一下寄存器中的数据:

  • x0是消息接收者,它是一个__NSGlobalBlock__,因为目前我们的block没有捕获任何的外部变量;

接下来我们将block代码修改如下:

继续执行代码到_Block_copy的符号断点,我们打印一下x0寄存器的数据:

  • 因为此时block捕获了外部变量,所以他此时是一个__NSStackBlock__,是个栈block;但是按照我们之前分析的结果,block捕获了外部变量,并且是强引用,它应该是一个堆block才对啊,这里为什么变成了栈block了,前后矛盾???

但是需要注意的是,此时我们的程序在断点过程中,_Block_copy还没有执行完毕!

那么我们在_Block_copy最后return的地方打上断点,向下执行,我么你看一下returnx0寄存器中的情况:

  • _Block_copy方法开始执行时,与执行完毕之后return时,x0寄存器地址发生了变化,并且从__NSStackBlock__变成了__NSMallocBlock__;
  • _Block_copy方法将一个栈block变成了堆block

我们现在从汇编角度分析出了block的变化,接下来我们从源码中分析验证一下;

源码分析block流程

_Block_copy的源码实现如下:

解析:

  • (aBlock->flags & BLOCK_NEEDS_FREE)如果block被标识为释放的,那么直接return;
  • (aBlock->flags & BLOCK_IS_GLOBAL)如果block被标识为全局的,那么直接return;
  • size_t size = Block_size(aBlock);获取block的大小;
  • struct Block_layout *result = (struct Block_layout *)malloc(size)按照大小开辟内存空间;
  • memmove(result, aBlock, size)将aBlock拷贝到result中;
  • result->isa = _NSConcreteMallocBlockblock重新标记为堆block;

编译期生成的只能是栈block,因为在编译期没有alloc等操作,没有内存的开辟,所以只能标记为栈block,然后在运行时重新将栈block标记为堆block

我们仔细查看控制台打印信息的时候发现,除了打印出以上内容之后,还打印出了signature: "v8@?0"invokecopydispose这些信息;那么他们都是什么东西呢?

  • signature是我们当前block的签名; 我们可以通过下面的方式来查看这个签名信息:

  • 解析

    • number of arguments = 1:传递了1个参数;
    • is special struct return? NO:没有返回值;
    • argument 0::参数从0号位置开始;
    • flags {isObject, isBlock}:是一个block,也是一个对象,也就是一个block类型的对象;
  • invoke是函数的调用者的指针;

那么copydisposeblock有什么影响呢?我们下次继续讲解......