2012-02-20 38 views
2

我得到了一個帶SIGSEGV的iPhone崩潰報告,我想我已經縮小了可能的原因和解決方案。 由於線程造成的崩潰很難調試,我不能重複這個問題,但可以用我的假設一些幫助 - 這聽起來嗎?Objective-C線程安全代碼以防止崩潰

我的代碼使用ASIHttpRequest使用ASINetWorkQueue下載一組文件。下面是一個簡化的樣品

//initialize download queue and do this code block in a loop for each file 

NSURL *fileURL = [NSURL URLWithString:... 
__block ASIHTTPRequest *fileRequest = [ASIHTTPRequest requestWithURL:fileURL]; 

[fileRequest setCompletionBlock:^{ 
    //do some stuff 
}]; 
[fileRequest setFailedBlock:^{ 
    NSString *someError = [NSString stringWithFormat:... 
    [self someErrorMethod:someError];  
}]; 

[downloadQueue addOperation:... 

-(void)someErrorMethod(NSString *errorMessage) { 
    DDLogWarn(errorMessage); 

    if ([self downloadQueue]) { 
     for (ASIHTTPRequest *request in [[self downloadQueue] operations]) { 
      [request clearDelegatesAndCancel]; 
     } 
     [[self downloadQueue] reset]; 
    } 
} 

頂部2行碰撞報告的是

  • libobjc.A.dylib 0x31846fbc objc_msgSend + 15
  • MyApp的0x0002cab5 - [Myapp someErrorMethod:](MyApp.m :)

我爲什麼發生這種情況

  • 一個文件下載失敗,失敗的塊被稱爲
  • 它經過的每個請求,並清除代表和取消它們,然後重置隊列思維
  • 但是,當它一直運行時,另一個文件下載失敗並進入失敗的塊回調
  • 但是,由於它現在已被取消,其失敗的塊已被釋放
  • 當代碼試圖登錄該錯誤消息,它的內存已經被釋放和不可預知的結果如下

這是否有道理?由於我對Objective-C很陌生,我的分析是正確的還是缺少明顯的東西?

我想使用鎖來使errorMethod線程安全,希望它能解決這個問題。這聽起來像是基於上述代碼的正確解決方案嗎?

謝謝

+1

不知道你的錯誤,但你可能想看看這個:http://stackoverflow.com/a/5023583/330494你應該使用blocksafeSelf來引用自己與伊娃爾塊。 – 2012-02-20 16:35:04

+0

謝謝巴洛 我在這裏使用一個單一類,永遠不會被釋放,所以我不認爲保留週期是一個問題,對不對? – suhail 2012-02-23 03:09:33

回答

4

聽起來不太可能。 ASIHttpRequest可能在同一個線程上執行所有的回調(我對此非常肯定)。

如果我猜的話,你的錯誤很可能在這一行:

DDLogWarn(errorMessage); 

的第一個參數DDLogWarn是一種格式,而不是一個字符串。在任何情況下,這可能會崩潰,errorMessage包括%。你的意思是:

DDLogWarn(@"%@", errorMessage); 

由於DDLogWarn()是varags方法,它會開始替換(隨機)值它找到的堆棧字符串中的任何%替換上。它會讀取堆棧,直到耗盡%替換值。如果任何%替換都是基於指針的(例如%s或%@),則它會跟隨指向隨機位置的指針。

SEG_ACCERR表示你已經請求了你不擁有的一塊內存。 SEG_MAPERR表示您已請求一段未映射的內存。要麼是跟隨完全隨機指針的預期結果。

+0

感謝您的迴應Rob。 這確實是我錯過的愚蠢。但是,會導致SEGV_ACCERR? 我試過用字符串在%至攝製,並得到了SEGV_MAPERR代替 libobjc.A.dylib 0x0262509b objc_msgSend + 15 的CoreFoundation 0x0245f6f8 __CFStringAppendFormatCore 的CoreFoundation 0x023aab6c _CFStringCreateWithFormatAndArgumentsAux 基金會0x0137f1a5 - [NSPlaceholderString initWithFormat:區域:參數:] Foundation 0x013cc66e - [NSString initWithFormat:arguments:] MyApp 0x00062867 + [DDLog log:level:flag:context:file:function:line:format:] – suhail 2012-02-22 18:05:32

+0

已更新;預計任何形式的SEGV。 – 2012-02-22 20:10:24