关于Block的内存问题__上

block传值绝对是工作中非常普遍的, block的原理要明白

先写一个最简单的block(这里用的都是MRC)

void (^myBlock)() = ^{
    NSLog(@"我的block");
};
NSLog(@"%@",myBlock);

block相当于一个方法的定义, 不调用是不会执行的, 打印block, 结果是
打印block结果

接下来引入一个静态变量a

        static int a = 10;
        void (^myBlock)() = ^{
            NSLog(@"我的block, a = %d", a);
        };
        NSLog(@"%@",myBlock);
        myBlock();

打印结果:
引入静态变量的打印结果
通过NSGlobalBlock可以看出两次的打印block的结果都是显示block在全局静态区, 同样对于引入全局变量打印结果也是不变的
总结1:
MRC下当声明的block实现部分, 没有引入外界的任何局部变量, 或者引入全局变量或者static变量, 那么该block位于全局静态区, 此时block的内存不需要程序员管理, 程序运行结束时, 内存被系统回收

接下来是另一种情况: 这里把静态变量换成了局部变量

        int a = 10;
        void (^myBlock)() = ^{
            NSLog(@"我的block, a = %d", a);
        };
        NSLog(@"%@",myBlock);
        myBlock();

打印结果:
这里写图片描述
可以看出打印block的结果是NSStackBlock 说明此时的block在栈区
总结2:
当block中引入局部变量, 此时block位于栈区(stack), 出了函数作用域, 该内存就被释放掉了, 在执行回调的时候, 使用栈区的block非常危险, 容易造成野指针问题, **这就是为什么block要使用copy的原因(包含基础类型和自定义的类对象)

接下来看另外两种情况:这里将myBlock拷贝了一次, 分别引入局部变量和静态变量

        int a = 10;
        void (^myBlock)() = ^{
            NSLog(@"我的block, a = %d", a);
        };
        NSLog(@"%@", Block_copy(myBlock));
        myBlock();

打印结果:
这里写图片描述
引入局部变量并copy,此时的block就在malloc堆区存储

        static int a = 10;
        void (^myBlock)() = ^{
            NSLog(@"我的block, a = %d", a);
        };
        NSLog(@"%@", Block_copy(myBlock));
        myBlock();

打印结果:
这里写图片描述
引入静态变量并copy, block还在全局静态区
总结3:
对栈区的block进行操作, 此时block内存就会由栈迁徙到堆区, 我们对于全局静态区的block进行copy的话, 此时还在全局静态区

block在底层其实就是一个指向一个结构体的指针
*如果我们定义一个局部变量的时候传进结构体的是一个值
*当我们局部变量前面加上static和__block或者是一个全局变量的时候, 他们在传入结构体的时候, 相当于传入了一个变量的指针进来, 所以当我们在调用之前改变a的值得时候, 结果会发生变化
*当栈区的block引用的是一个对象类型的局部变量, 进行拷贝, 内存迁徙到堆区的时候, 引用计数+1;

在MRC中堆区的block内存需要进行释放
两种方法:
1. 在定义对象时类名前写上__block,(会进行拷贝的操作时) 告诉系统不要对所引入的对象类型进行引用计数+1;
2. 在最后写上BLock_release(myBlock);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值