[英]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.