美文网首页
__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