大佬教程收集整理的这篇文章主要介绍了ios – 为什么返回__strong和__autoreleasing变量只会在第一次产生不同的对象生命周期?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@implementation MyClass -(void)dealloc { NSLog(@"MyClass dealloc: %@",self); } @end @implementation AppDelegate __weak static MyClass *weakShared = nil; - (MyClass *)getMyClass { MyClass *tmpHolder = [[MyClass alloc] init]; // PREPEND "__autoreleasing" weakShared = tmpHolder; return weakShared; // ATTENTION TO THIS LINE } - (void)logMyClass:(NSUInteger)i { MyClass *mc = [self getMyClass]; NSLog(@"(%@) this is MyClass: %@",@(i),mc); } - (void)applicationDidFinishLaunching:(Nsnotification *)aNotification { @autoreleasepool { for (int i = 0; i < 10; i++) { [self logMyClass:i]; } NSLog(@"end"); } NSLog(@"outside pool"); }
注意标有//注意此线路的线路.
我可以用3种口味替换那条线:
> return weakShared(__ weak)
> return tmpHolder(__strong)
>将带有__autoreleasing的tmpHolder返回到上面指示的tmpHolder变量.
上述每种情况的输出是:
1.
(0) this is MyClass: <MyClass: 0x600000020490> MyClass dealloc: <MyClass: 0x600000020490> (1) this is MyClass: <MyClass: 0x600000024270> MyClass dealloc: <MyClass: 0x600000024270> (2) this is MyClass: <MyClass: 0x600000024270> MyClass dealloc: <MyClass: 0x600000024270> end outside pool
2.
(0) this is MyClass: <MyClass: 0x600000010570> (1) this is MyClass: <MyClass: 0x600000010530> MyClass dealloc: <MyClass: 0x600000010530> (2) this is MyClass: <MyClass: 0x600000010530> MyClass dealloc: <MyClass: 0x600000010530> end MyClass dealloc: <MyClass: 0x600000010570> outside pool
3.
(0) this is MyClass: <MyClass: 0x600000020060> (1) this is MyClass: <MyClass: 0x600000020040> (2) this is MyClass: <MyClass: 0x600000020030> end MyClass dealloc: <MyClass: 0x600000020030> MyClass dealloc: <MyClass: 0x600000020040> MyClass dealloc: <MyClass: 0x600000020060> outside pool
我的问题:为什么案例2的行为如此?我希望它能在返回之前自动释放我的变量,因此表现得像3;或者只是在没有自动释放的情况下返回它并且表现得像1.
注意:您将需要-Os标志来重现上述示例.
在迭代0中,由于ARC辅助函数的延迟绑定打破了返回值优化,因此将对象放入自动释放池中.其余的都会尽快释放,因为符号已被绑定.
案例2中的弱引用是红鲱鱼.删除weakShared变量后,您可以获得相同的行为.
@implementation AppDelegate -(MyClass*)getMyClass { MyClass* tmpHolder = [[MyClass alloc] init]; return tmpHolder; } ...
@H_699_7@myClass* "-[AppDelegate getMyClass]"(AppDelegate* self,SEL _cmd) { MyClass* tmpHolder = [[MyClass alloc] init]; return objc_autoreleaseReturnValue(tmpHolder); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ }
与ARC -autorelease之前的方法不同,objc_autoreleaseReturnValue()
function不会将对象直接移动到自动释放池中.它将检查调用者的汇编指令,如果调用者将立即“ – 保持”该值,我们将跳过自动释放池并直接返回1’ed对象.
void "-[AppDelegate logMyClass:]"(AppDelegate* self,SEL _cmd,NSUInteger i) { MyClass* mc = objc_retainAutoreleasedReturnValue([self getMyClass]); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NSnumber* ii = objc_retainAutoreleasedReturnValue([NSnumber numberWithInt:i]); NSLog(@"(%@) this is MyClass: %@",ii,mc); objc_release(ii); objc_release(mc); }
由于这种行为,在迭代1到9中,objc_autoreleaseReturnValue和objc_retainAutoreleasedReturnValue方法变为no-op,并且在-logMyClass:的末尾立即销毁那些MyClass实例.
(还有关于此返回优化如何在How does objc_retainAutoreleasedReturnValue work? by Matt Galloway上工作的详细说明.)
但是在迭代0发生了什么?
我们可以阅读implementation of callerAcceptsOptimizedReturn
,它描述了objc_autoreleaseReturnValue如何确定调用者将“立即保留”.简而言之,它将确保呼叫者在通话后立即获得以下指示:
48 89 c7 movq %rax,%rdi e8 __ __ __ __ callq <something>
解除引用< something>应该指出
ff 25 __ __ __ __ jmpq *<symbol>
其中< symbol>应该是objc_retainAutoreleasedReturnValue的函数指针.但是,如果您在调试器中运行该程序并跟踪objc_autoreleaseReturnValue,您将发现< symbol>在第一次通话时不是objc_retainAutoreleasedReturnValue!
原因是objc_retainAutoreleasedReturnValue是一个惰性符号(__DATA,__ la_symbol_ptr).链接到外部动态库时,这是the default behavior.在通过< symbol>进行调用之前,dynamic linker不会将其解析为正确的函数指针.
实际上,如果通过添加-bind_at_load
linker flag来禁用延迟绑定行为,则代码将与“case 1”的行为相同
$clang -fobjc-arc -framework Foundation -bind_at_load -Og 1.m $./a.out 2018-05-30 19:25:58.838 a.out[4923:19498647] (0) this is MyClass: <MyClass: 0x7fa392400200> 2018-05-30 19:25:58.838 a.out[4923:19498647] MyClass dealloc: <MyClass: 0x7fa392400200> 2018-05-30 19:25:58.838 a.out[4923:19498647] (1) this is MyClass: <MyClass: 0x7fa392400200> 2018-05-30 19:25:58.838 a.out[4923:19498647] MyClass dealloc: <MyClass: 0x7fa392400200> ... 2018-05-30 19:25:58.839 a.out[4923:19498647] (9) this is MyClass: <MyClass: 0x7fa392600400> 2018-05-30 19:25:58.839 a.out[4923:19498647] MyClass dealloc: <MyClass: 0x7fa392600400> 2018-05-30 19:25:58.839 a.out[4923:19498647] end 2018-05-30 19:25:58.839 a.out[4923:19498647] outside pool $
由于此问题仅在整个程序生命周期中发生一次,这可能是行为保持不变的原因.
LLDB脚本显示延迟加载行为:
以上是大佬教程为你收集整理的ios – 为什么返回__strong和__autoreleasing变量只会在第一次产生不同的对象生命周期?全部内容,希望文章能够帮你解决ios – 为什么返回__strong和__autoreleasing变量只会在第一次产生不同的对象生命周期?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。