【发布时间】:2012-01-20 17:35:31
【问题描述】:
我有一些类似于以下代码的代码:
dispatch_queue_t queue = dispatch_queue_create("", 0);
dispatch_queue_t inner_queue = dispatch_queue_create("", 0);
dispatch_async(queue,
^{
NSAutoreleasePool* autoreleasePool = [[NSAutoreleasePool alloc] init];
NSArray* objects = [self.otherObject getObjectsFromSlowQuery];
[objects enumerateObjectsWithUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop)
{
[anObject prepare];
dispatch_async(inner_queue,
^{
InnerObject* innerObject = anObject.innerObject;
[self.helper doSomethingExpensiveWithObject:innerObject];
});
dispatch_sync(self.syncQueue,
^{
[self insertIntoCollection:anObject];
});
}];
dispatch_release(inner_queue);
[autoreleasePool drain];
});
dispatch_release(queue);
其中[anObject.innerObject] 是nonatomic 属性。
当我尝试在doSomethingExpensiveWithObject: 调用中访问innerObject 的属性时,我收到了来自用户的崩溃报告,其中显示objc_msgSend() 中的EXC_BAD_ACCESS。
起初我在想autoreleasePool 可能已经耗尽,所以innerObject 实例在从doSomethingExpensiveWithObject: 返回之前被释放,但据我所知anObject 应该由内部dispatch_async 调用保留还应该保持innerObject 活着。
我错过了什么?
【问题讨论】:
-
代码在没有队列的情况下可以工作吗?另外,你don't need to allocate an NSAutoreleasePool在这里。
-
块不会影响它们捕获的对象的保留计数。
-
@user1139069: They do. 这就是为什么需要
__block来关闭它(并使块能够修改变量)。 -
@user1139069
dispatch_async调用Block_copy将变量保留在块范围内。 -
没有特别证据表明自动释放池与崩溃有关。但是使用
dispatch_async意味着该块可能在具有自己的自动释放池的其他线程上运行(在每个块运行后可能不会被耗尽)。因此,如果您认为doSomethingExpensiveWithObject:需要它,您应该在inner_queue块内创建/排出一个池。
标签: objective-c exc-bad-access grand-central-dispatch nsautoreleasepool