[英]Weird bad_access with dispatch_async
使用调度异步时,我收到了一个非常奇怪的错误访问错误。 我设法将其缩减为程序中的这段代码。
-(void)buttonTapped:(id)sender {
__block NSArray*foo = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
//Foo was initially declared here but then moved it outside.
foo = [self someMethod];
[foo retain]; // bad access here. Why ?
dispatch_async(dispatch_get_main_queue(),0) {
// doesnt matter what happens here
}); });
}
-(id)someMethod
{
return [self secondMethod];
}
-(id)secondMethod
{
// was initially returning an autoreleased object from here. Changed it
// to eliminate that as source of the error.
id newThing = [[NSObject alloc] init];
return newThing;
}
该代码最初看起来不是这样,但是现在是这样。 包括分配虚拟NSObject。
foo如何在调度异步内部的调用之间释放? 我不明白这怎么可能。 我知道很难建议仅此而已,但是任何调试建议都将有所帮助。 我尝试打开NSZombies,但没有任何僵尸。
你问:
foo
如何在dispatch_async
内部的dispatch_async
调用之间被释放?
除非someMethod
或secondMethod
自己进行,否则不应该异步执行某些操作,这可能会使自动释放池在此期间耗尽。
我尝试打开
NSZombies
但没有任何僵尸。
如果您打开了僵尸,但又没有遇到僵尸,那么我怀疑问题出在其他地方。 坦率地说,我怀疑问题的根源在简化示例代码以解决问题的过程中被消除了:
其他一些观察/说明:
您声明foo
为NSArray
,但随后返回NSObject
。 我假设您的意思是整个都是NSObject
。
您有一行代码说:
dispatch_async(dispatch_get_main_queue(),0) {
我只是假设这是一个错字,并且您打算这样做:
dispatch_async(dispatch_get_main_queue(), ^{
foo
变量一定应该在dispatch_async
块内。 __block
变量用于某个东西(a),您没有在该块之外为某个块引用,这实际上没有任何意义。 (b)对于您异步分发的代码块。
secondMethod
应该返回一个autorelease
对象,就像您最初拥有的那样。 (或者你可能想改变secondMethod
和someMethod
开始与new
的自己的名字,以避免混淆,使生活为自己容易当你最终会转移到ARC)。
如果retain
foo
对象,则还需要添加相应的release
。 实际上,您的原始代码示例返回一个+1对象,然后再次将其保留,将其增大到+2,因此您需要两次release
调用。
无论如何,要纠正这些各种问题,我得到以下结果,它不会产生异常:
- (IBAction)buttonTapped:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSObject *foo = [self someMethod];
[foo retain]; // no bad access here
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"foo = %@", foo);
[foo release];
});
});
}
- (NSObject *)someMethod
{
return [self secondMethod];
}
- (NSObject *)secondMethod
{
return [[[NSObject alloc] init] autorelease];
}
此外,我建议特别是在使用手动保留和释放(MRR)时,通过静态分析器(在Xcode“产品”菜单上的“分析”)运行它,并确保您的健康状况良好。 (它会指出我提到的一些问题。)它不是完美的,但在识别问题方面非常出色。
但是,简而言之,上面的代码很好,并且如果您仍然遇到异常,请使用可重现异常的工作代码来更新您的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.