考虑下面的代码块属性直接设置崩溃iOS版:当访问
self.someA = [[ClassA alloc] init];
[self.someA giveBlock:^{
NSLog(@"self = %@", self);
}];
dispatch_async(dispatch_get_main_queue(), ^{
self.someA.blockCopy();
self.someA = nil;
});
如果我运行内置的O3
,启用了ARC,在iOS上,它在objc_retain
内的self.someA.blockCopy();
调用期间崩溃。为什么?
现在我意识到人们可能会说我应该用self.blockCopy = inBlock
来设置它,但我确实认为ARC应该在这里做正确的事情。
.align 2
.code 16
.thumb_func "-[ClassA giveBlock:]"
"-[ClassA giveBlock:]":
push {r7, lr}
movw r1, :lower16:(_OBJC_IVAR_$_ClassA.blockCopy-(LPC0_0+4))
mov r7, sp
movt r1, :upper16:(_OBJC_IVAR_$_ClassA.blockCopy-(LPC0_0+4))
LPC0_0:
add r1, pc
ldr r1, [r1]
add r0, r1
mov r1, r2
blx _objc_storeStrong
pop {r7, pc}
正在调用objc_storeStrong
这又做了块上的retain
和老块上的release
:如果我看的组件(ARMv7的)从giveBlock:
方法,它看起来像这样产生的。我的猜测是ARC没有正确地注意到它是一个块属性,因为我认为它应该调用objc_retainBlock
而不是正常的objc_retain
。
或者,我只是完全错误,实际上ARC正在做它的文件,我刚刚读了它的错误方式?
非常欢迎讨论 - 我觉得这很有趣。
注意要点:
- 它不会在OS X
- 它不会崩溃建
O0
崩溃。
虽然在分配时看到“objc_storeStrong”,但我没有能够“做正确的事情”,我只是有点惊讶。 – mattjgalloway 2012-01-11 19:00:14
+1有趣! – Till 2012-01-11 19:02:08
根据我的理解(有一段时间),有些情况会阻止编译器发出在所有情况下都“正常工作”的代码。在ARC之下,沙地中的坚硬线条要求编译器能够准确地证明任何给定的代码模式始终在任何地方都能正常工作。在这种情况下,它不能这样做,因为通过任何给定调用站点(包括'objc_storeStrong()')传递的仅堆栈块参数有效。 – bbum 2012-01-11 20:56:51