簡體   English   中英

使用dispatch_async奇怪的bad_access

[英]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調用之間被釋放?

除非someMethodsecondMethod自己進行,否則不應該異步執行某些操作,這可能會使自動釋放池在此期間耗盡。

我嘗試打開NSZombies但沒有任何僵屍。

如果您打開了僵屍,但又沒有遇到僵屍,那么我懷疑問題出在其他地方。 坦率地說,我懷疑問題的根源在簡化示例代碼以解決問題的過程中被消除了:

其他一些觀察/說明:

  1. 您聲明fooNSArray ,但隨后返回NSObject 我假設您的意思是整個都是NSObject

  2. 您有一行代碼說:

     dispatch_async(dispatch_get_main_queue(),0) { 

    我只是假設這是一個錯字,並且您打算這樣做:

     dispatch_async(dispatch_get_main_queue(), ^{ 
  3. foo變量一定應該在dispatch_async塊內。 __block變量用於某個東西(a),您沒有在該塊之外為某個塊引用,這實際上沒有任何意義。 (b)對於您異步分發的代碼塊。

  4. secondMethod應該返回一個autorelease對象,就像您最初擁有的那樣。 (或者你可能想改變secondMethodsomeMethod開始與new的自己的名字,以避免混淆,使生活為自己容易當你最終會轉移到ARC)。

  5. 如果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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM