专栏首页老沙课堂block内存管理

block内存管理

1. 在某些ARC情况 会将栈内的block copy到 堆 中

  1. block 在作为函数返回值的时候 会自动copy操作 在函数中作为返回值的时候。生成的是盏中的block 在函数结束后,如果block在盏中,有可能会被销毁,当我们在调用的时候,会发生错误。所以会对block进行 copy操作 copy到堆中,确保后续操作正确.
  2. Block 被强指针引用 int a = 10;void(^test)(void) = ^{ NSLog(@"%d",a);};NSLog(@"%@",[test class]); NSLog(@"%@",[^{ NSLog(@"%d",a); } 打印结果为 ARC 2019-08-21 14:20:55.125206+0800 Block内部实现原理[96810:14357802] __NSMallocBlock__2019-08-21 14:20:55.125244+0800 Block内部实现原理[96810:14357802] __NSStackBlock__
  3. block作为Cocoa API中方法名含有usingBlock方法参数时 例如[Array enum]遍历
  4. GCD中的block

2. copy

盏空间的block 不会对外面capture的变量进行强引用 无论weak修饰 还是strong修饰

堆空间的block 对外面capture的变量进行强引用

__weak 修饰后 block结构体中引用对象也会变成 __weak

当对block进行copy操作的

block desc中会添加两个方法

  • __main_block_copy_0
  • __main_block_dispose

copy会调用block_object_assign函数

Block_object_assign 自动根据capture到的变量的引用是weak还是strong 来进行操作 类似于retain

在block从堆上移除会调用__main_block_dispose

__main_block_dispose会调用_Block_object_dispose_Block_object_dispose函数会自动释放引用的变量, 类似release

3. __block

我们书写下下面代码 然后看一下rewrite-objc 后生成什么

__block NSObject *person = [NSObject new];    void (^testBlock)(void) = ^(void) {  NSLog(@"%@",person);// person 为__block结构体中的person};
__attribute__((__blocks__(byref))) __Block_byref_person_0 person = {            (void*)0,            (__Block_byref_person_0 *)&person,            33554432,            sizeof(__Block_byref_person_0),            __Block_byref_id_object_copy_131,            __Block_byref_id_object_dispose_131,            ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("new"))};

当被__block 修饰后的persion 会被构造到个结构体__Block_byref_person_0

struct __Block_byref_person_0 {  void *__isa;  // isa  __Block_byref_person_0 *__forwarding; //指向自己的指针 当block从栈copy到堆中  则指向堆中block的地址 int __flags; // 标记 int __size; // 大小 void (*__Block_byref_id_object_copy)(void*, void*); // 当block被拷贝到堆中执行此方法 void (*__Block_byref_id_object_dispose)(void*);  // 当block释放 执行这个方法 NSObject *person; //persion};

在ARC环境下 block在赋值的时候 会发生拷贝。具体的指向由下图所示。

__block __weak NSObject *person = [NSObject new]; 修饰符为weak时 弱引用 其他时候为强引用

这样的结构的好处是无论我们从栈中去找block找到__forwrding 还是堆中block__forwarding找person的时候,都能够找到堆中的block 中的person 这样就确保person的存在。

4. 循环引用

__weak unsafe_unretain __block 里面

因为__block生成的结构体类似中间变量,所以在循环引用个的时候是一个三角结构,我们在在block中将__block修饰的变量置为nil 既可解决循环引用。如下图

本文分享自微信公众号 - 老沙课堂(gh_f73a6b772d4f),作者:rui4u

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • block内部实现

    c. 我们先看一下__ main_block_impl_0结构体和 __ main_block_func_0 还有__main_block_desc_0_DAT...

    老沙
  • 据结构与算法(十) AVL树

    因为无法改变添加删除顺序(用户操作决定),所以在每次操作之后,让二叉树达到平衡状态。

    老沙
  • 数据结构与算法(一) 简单例子理解时间复杂度和空间复杂度

    所以总的时间为1 + n + n + n + n^2 + n^2 + n^2 = 1 +3n +3n^2 由于计算时间复杂度可以省略常数,系数以及低阶 所以这个...

    老沙
  • 【iOS】block小记

    VV木公子
  • 编译器 bug 系列(1)

    作为客户端开发者,我们每天都在接触编译器带来的便利,避免了手写机器码的麻烦,但是,某些情况下,编译器也会代码很多负面的作用。

    酷酷的哀殿
  • 面试驱动技术 - Block看我就够了【干货】

    Block 在 iOS 算比较常见常用且常考的了,现在面试中,要么没面试题,有面试题的,基本都会考到 block 的点。本文特别干!(但是初中级iOSer应该能...

    小蠢驴打代码
  • 细说 MySQL 之 MEM_ROOT

    这篇文章会详细解说MySQL中使用非常广泛的MEM_ROOT的结构体,同时省去debug部分的信息,仅分析正常情况下,mysql中使用MEM_ROOT来做内存分...

    哲洛不闹
  • 编码篇-Block里面的小天地

    Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。 通常来说,block都是一些简短代码片段的封装,适...

    進无尽
  • iOS中Block的用法,举例,解析与底层原理(这可能是最详细的Block解析)

    【摘要】这篇文章,首先在第1节中介绍Block的定义,以及与C里面函数的对比。然后,第2节介绍实际开发中经常会用到的Block语法形式,以供读者日后查阅。只知道...

    陈满iOS
  • iOS block的一些理解和注意点

    大壮

扫码关注云+社区

领取腾讯云代金券