2012-02-20 60 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