【问题标题】:Why is ObjC block released when it captures a variable and not when it does not?为什么 ObjC 块在捕获变量时释放而不是在没有时释放?
【发布时间】:2013-05-18 09:28:34
【问题描述】:

例子:

extern void _objc_autoreleasePoolPrint();

int main(int argc, char *argv[])
{

    @autoreleasepool {

        id __weak blk;

        {
            int a = 10;

            blk = ^(NSString *msg){
                NSLog(@"msg: %@", msg);
                NSLog(@"%d", a);
            };
        }

        NSLog(@"blk: %@", blk);

        _objc_autoreleasePoolPrint();

        ((void (^)(NSString *))blk)(@"Hello!");

    }

    return 0;
}

输出是:

2013-05-18 13:24:10.355 __iOS_SimpleConsoleApplication[63449:c07] blk: (null)
objc[63449]: ##############
objc[63449]: AUTORELEASE POOLS for thread 0xac583a28
objc[63449]: 1 releases pending.
objc[63449]: [0x7a73000]  ................  PAGE  (hot) (cold)
objc[63449]: [0x7a73028]  ################  POOL 0x7a73028
objc[63449]: ##############

然后崩溃:)

在将块分配给__weak blk 变量后,它会在自动释放池中注册,因此离开范围后它不应该等于nil,但确实如此!为什么?

从 blk 捕获的变量“a”中删除后,我有以下输出:

2013-05-18 13:25:34.132 __iOS_SimpleConsoleApplication[63486:c07] blk: <__NSGlobalBlock__: 0x35d0>
objc[63486]: ##############
objc[63486]: AUTORELEASE POOLS for thread 0xac583a28
objc[63486]: 2 releases pending.
objc[63486]: [0x7923000]  ................  PAGE  (hot) (cold)
objc[63486]: [0x7923028]  ################  POOL 0x7923028
objc[63486]: [0x792302c]            0x35d0  __NSGlobalBlock__
objc[63486]: ##############
2013-05-18 13:25:34.142 __iOS_SimpleConsoleApplication[63486:c07] msg: Hello!

没有任何崩溃。

【问题讨论】:

    标签: objective-c objective-c-blocks weak-references


    【解决方案1】:

    知道了!

    使用没有捕获变量的块,它被添加到_NSGlobalBlock内存段,因此它的内存地址总是有效的,但是当块捕获变量“a”时,它被添加到_NSStackBlock内存段并在离开范围后被释放。

    要使用捕获的变量,我们应该使用复制方法,该块将被移动到_NSMallocBlock内存段。

    extern void _objc_autoreleasePoolPrint();
    
    int main(int argc, char *argv[])
    {
    
        @autoreleasepool {
    
            id blk;
    
            {
                int a = 10;
    
                blk = [^(NSString *msg){
                    NSLog(@"msg: %@", msg);
                    NSLog(@"a: %d", a);
                } copy];
    
            }
    
            NSLog(@"blk: %@", blk);
    
            _objc_autoreleasePoolPrint();
    
            ((void (^)(NSString *))blk)(@"Hello!");
    
        }
    
        return 0;
    }
    

    输出:

    2013-05-18 13:43:51.947 __iOS_SimpleConsoleApplication[63822:c07] blk: <__NSMallocBlock__: 0x7190120>
    objc[63822]: ##############
    objc[63822]: AUTORELEASE POOLS for thread 0xac583a28
    objc[63822]: 1 releases pending.
    objc[63822]: [0x7b9f000]  ................  PAGE  (hot) (cold)
    objc[63822]: [0x7b9f028]  ################  POOL 0x7b9f028
    objc[63822]: ##############
    2013-05-18 13:43:51.952 __iOS_SimpleConsoleApplication[63822:c07] msg: Hello!
    2013-05-18 13:43:51.952 __iOS_SimpleConsoleApplication[63822:c07] a: 10
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 2013-12-11
      相关资源
      最近更新 更多