block

作者: 天蚕 | 来源:发表于2019-01-02 11:09 被阅读1次

    为什么block使用copy(ARC下也可以使用strong)

    为的是将block拷贝到堆上来

    // MRC
    1、block类似于函数指针,但是有时内联的(代码直接插入到调用者处,免去了普通函数调用的过程,效率更高)
    2、block是一个代码片段,在OC中被看作是OC对象
    3、block建议使用copy或者strong策略
    4、block分为三种__NSGlobalBlock__,__NSMallocBlock__,__NSStackBlock__
    MRC默认情况下是__NSGlobalBlock__,使用(捕获)了外部非static和全局的变量会变成__NSStackBlock__,__NSStackBlock__的block使用了copy策略,就变成__NSMallocBlock__的了
    // ARC下
    1、如果使用
    ARC默认情况下是__NSGlobalBlock__,使用(捕获)了外部非static和全局的变量会变成__NSStackBlock__,将__NSStackBlock__赋值给变量或者属性(非assign,使用assign还是__NSStackBlock__,使用了copy和strong都一样)系统默认将会发生copy操作到栈上,变成__NSMallocBlock__
    5、在MRC和ARC下都不要使用assign策略
    
    为什么将block拷贝到堆上来
    1、block拷贝到堆上来基本是为了处理__NSStackBlock__,捕获外部变量(因为不捕获外部变量的时候,__NSGlobalBlock__是静态区的,这个内存区域是不会这几销毁,不存在内存问题)
    2、__NSStackBlock__之所以会出现内存问题是因为,在栈区内存是系统自动管理的,会被自动释放掉(计数器为0的时候,以保证内存不至于太过消耗,甚至爆栈);自动释放后block的本质是一个结构体指针,原本指向它的指针地址还是在的这就是空指针,即便我们把block赋值为nil,地址还是0x0(空指针);一旦我们再区调用block无论是野指针还是指针都会crash。只有将block搞到堆上来,我们能购保证block的内存不会被自动释放,在我们不需要的情况下,block置为nil让ARC自动管理内存即可。
    3、区别于OC可以给nil发送消息,OC会自动在发送消息的时候去判断接受消息的对象是不是nil,是nil发送函数objc_msgSend会直接return的,block是直接去寻址一个内存地址(void *FuncPtr)去执行的。
    

    block为什么需要判空

    // oc
    int main() {
        void(^testBlock)();
        testBlock();
    }
    // clang -rewrite-objc
    int main() {
        void(*testBlock)();
        ((void (*)(__block_impl *))((__block_impl *)testBlock)->FuncPtr)((__block_impl *)testBlock);
    }
    // block结构体
    struct __block_impl {
      void *isa;
      int Flags;
      int Reserved;
      void *FuncPtr;
    };
    

    上面OC代码直接运行会直接crash。用clangOC代码翻译成C++代码,我们就会发现,testBlock();被翻译为一个执行返回(void (*)(__block_impl *))类型且有一个参数(__block_impl *)testBlock的函数((__block_impl *)testBlock)->FuncPtr;我们看到testBlock强制转换成了结构体指针__block_impl *,block最终调用的是__block_impl结构体中的FuncPtr;而此时的testBlock并没有赋值只是一个nil,地址是0x0,加上FuncPtr是结构体中的第四个成员变量,void *占8个字节,int类型占4个字节,那么FuncPtr的执行地址是在0x0的基础上向后移动8 + 4 + 4,一共16个字节,就是0x10;(在32位系统下void *占4个字节,最终寻址地址应该是0x0c

    相关文章

      网友评论

          本文标题:block

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