块存储管理的一个边缘壳体下面的代码会崩溃,因为EXC_BAD_ACCESS
理解objc
typedef void(^myBlock)(void);
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *tmp = [self getBlockArray];
myBlock block = tmp[0];
block();
}
- (id)getBlockArray {
int val = 10;
//crash version
return [[NSArray alloc] initWithObjects:
^{NSLog(@"blk0:%d", val);},
^{NSLog(@"blk1:%d", val);}, nil];
//won't crash version
// return @[^{NSLog(@"block0: %d", val);}, ^{NSLog(@"block1: %d", val);}];
}
代码在IOS 9 ARC运行启用。我试图找出导致崩溃的原因。
通过po tmp
在LLDB我发现
(lldb) po tmp
<__NSArrayI 0x7fa0f1546330>(
<__NSMallocBlock__: 0x7fa0f15a0fd0>,
<__NSStackBlock__: 0x7fff524e2b60>
)
而在不会崩溃版本
(lldb) po tmp
<__NSArrayI 0x7f9db481e6a0>(
<__NSMallocBlock__: 0x7f9db27e09a0>,
<__NSMallocBlock__: 0x7f9db2718f50>
)
所以最可能的原因,我能想出是当ARC释放NSStackBlock崩溃发生。但为什么会这样呢?
感谢您的详细解答。我相信C可变参数不是类型安全的,这是对这种情况更准确的解释。 – dopcn
@dopcn - newacct我倾向于不同意规范在块和ARC方面的状态。不幸的是,苹果的文档并不总是那么清晰和全面,并且不仅仅是公平的,而且涉及到一定程度的解释。请将您的案例作为一个错误提交给Apple;他们可以修复它,说它按预期工作,或者什么都不说;但你会提醒他们。如果他们确实回复了有用的回复,可以将其添加到上面的问题中作为帮助其他人的附录。 – CRD