美文网首页
__strong,__weak,__unsafe_unretai

__strong,__weak,__unsafe_unretai

作者: 传说中的汽水枪 | 来源:发表于2019-07-09 11:35 被阅读0次

    可以使用如下的两个命令来分别生成中间代码和优化后的中间代码,
    这样我们可以更好的跟踪ARC下OC的内存管理

    使用命令(生成中间代码):

    clang -S -fobjc-arc -emit-llvm code.m -o code.ll  
    

    使用命令(生成优化后的中间代码):

    clang -O3 -S -fobjc-arc -emit-llvm code.m -o code2.ll
    

    类:RXAAAA

    样本函数

    + (id)array {
        return [[NSMutableArray alloc] init];
    }
    

    生成后的模拟代码和优化后的模拟代码:

    // 模拟代码
    id obj = obj_msgSend(NSMutableArray, @selector(alloc));
    obj_msgSend(obj, @selector(init));
    return objc_autoreleaseReturnValue(obj);
    // 优化后的模拟代码
    id obj = obj_msgSend(NSMutableArray, @selector(alloc));
    obj_msgSend(obj, @selector(init));
    return objc_autoreleaseReturnValue(obj);
    

    此处没有优化

    __strong

    + (void)test1 {
        __strong id value = [RXAAAA array];
    }
    

    生成后的模拟代码和优化后的模拟代码:

    // 模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    id value;
    objc_storeStrong(&value, obj);
    // 优化后的模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    objc_release(obj);
    

    此处有优化,objc_autoreleaseReturnValueobjc_retainAutoreleasedReturnValue成对出现优化后省去了向autoreleasepool中注册了。

    __weak

    + (void)test2 {
        __weak id value = [RXAAAA array];
    }
    

    生成后的模拟代码和优化后的模拟代码:

    // 模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    id value;
    objc_initWeak(&value, obj);
    objc_release(obj);
    objc_destroyWeak(value);
    // 优化后的模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    id value;
    objc_initWeak(&value, obj);
    objc_release(obj);
    objc_destroyWeak(value);
    

    从这里可以看出,编译器没有做优化,当把一个方法返回值obj对象赋值给__weak的时候,这个obj会立刻释放掉,所以__weak的变量值也会马上被置为空。

    __unsafe_unretained

    + (void)test3 {
        __unsafe_unretained id value = [RXAAAA array];
    }
    

    生成后的模拟代码和优化后的模拟代码:

    // 模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    id value = objc_unsafeClaimAutoreleasedReturnValue(obj);
    // 优化后的模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    id value = objc_unsafeClaimAutoreleasedReturnValue(obj);
    

    没有做任何优化,在此方法内部使用这个__unsafe_unretained变量是没有问题的,但是如果属性设置成__unsafe_unretained就会容易出现野指针的现象。

    __autoreleasing

    + (void)test4 {
        __autoreleasing id value = [RXAAAA array];
    }
    

    生成后的模拟代码和优化后的模拟代码:

    // 模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    id value = objc_autorelease(obj);
    // 优化后的模拟代码
    id obj = obj_msgSend(RXAAAA, @selector(array));
    id value = objc_retainAutoreleasedReturnValue(obj);
    objc_release(value);
    

    这里也优化了,把原来添加两次到autoreleasepool,变成了一次都不添加,然后直接在当前作用域就释放了。

    __autoreleasing && @autoreleasepool

    + (void)test5 {
        @autoreleasepool {
            __autoreleasing id value = [RXAAAA array];
        }
    }
    

    生成后的模拟代码和优化后的模拟代码:

    // 模拟代码
    id pool = objc_autoreleasePoolPush();
    id obj = obj_msgSend(RXAAAA, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    id value = objc_autorelease(obj);
    objc_autoreleasePoolPop(pool);
    // 优化后的模拟代码
    id pool = objc_autoreleasePoolPush();
    id obj = obj_msgSend(RXAAAA, @selector(array));
    id value = objc_retainAutoreleasedReturnValue(obj);
    objc_release(value);
    objc_autoreleasePoolPop(pool);
    

    这里也是优化了,把两次添加到autorelease变成0次添加。

    以上就是OC中变量所有权的带有ARC的中间代码和优化后的代码初步探索。

    相关文章

      网友评论

          本文标题:__strong,__weak,__unsafe_unretai

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