可以使用如下的两个命令来分别生成中间代码和优化后的中间代码,
这样我们可以更好的跟踪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_autoreleaseReturnValue
和objc_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的中间代码和优化后的代码初步探索。
网友评论