4

アプリケーションで発生したクラッシュを再現するために、実用的ではないかもしれないわずかに誇張された繰り返し率のサンプルを作成する必要がありましたが、アプリで何が起こっているかを正確に示しています。を使用してバックグラウンドスレッドでNSStringを描画するNSOperationsと、クラッシュが発生する前にスタックトレースの最後の呼び出しでクラッシュが発生することがあります。WebCore::FontFallbackList::~FontFallBackList().

- (void)viewDidLoad
{
    queue = [[NSOperationQueue alloc] init];
    [NSTimer scheduledTimerWithTimeInterval:0.0001 target:self selector:@selector(timerDidFire:) userInfo:nil repeats:YES];
}

-(void)timerDidFire:(NSTimer*)timer
{
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        CGRect rect = CGRectMake(0, 0, 50, 50);
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(rect.size.width, rect.size.height), YES, 0.0);
        NSString *string = @"Sd";
        [string drawInRect:rect withFont:[UIFont boldSystemFontOfSize:12] lineBreakMode:UILineBreakModeTailTruncation]; 
        UIGraphicsEndImageContext();     
    }];
    [queue addOperation:op];
}

上記のコードを使用すると、このクラッシュを簡単に再現できます。このクラッシュの性質と、なぜそれが起こっているのかについて、誰かが洞察を持っていますか?(この問題の解決策は設定です[queue setMaxConcurrentOperations:1];

4

3 に答える 3

5

これは iOS 5.x の回帰のようです。5.0 および 5.1 シミュレーターと 5.1 デバイスで発生しますが、4.3 シミュレーターまたは 4.3.2 デバイスでは発生しません。

壊れているように見えるのは、特に文字列の描画でもあります — 文字列の描画 (コンテキストの作成/破棄のオーバーヘッドを回避する) だけの場合、クラッシュはほぼ瞬時に発生します。

-(void)threadFunc:(UIFont *)font {
  @autoreleasepool {
    NSString *string = @" ";
    CGRect r = {{0,0},{50,50}};
    UIGraphicsBeginImageContextWithOptions(r.size, YES, 0);
    for(;;) {
      @autoreleasepool {
        [string drawAtPoint:r.origin withFont:font];
      }
    }
    UIGraphicsEndImageContext();
  }
}

-(void)startThreads
{
  UIFont * font = [UIFont systemFontOfSize:12];
  for (int i = 2; i--;)
  {
    [NSThread detachNewThreadSelector:@selector(threadFunc:) toTarget:self withObject:font];
  }
}

EDIT:マルチコア環境(マルチコアMacを想定したデュアルコアデバイスまたはシミュレータ)でのみ「ほぼ瞬時」です。そうしないと、クラッシュするのに 10 ~ 20 分程度かかります。私はデュアルコアの iOS 4.x デバイスを持っていません (唯一の可能性は iPad 2 のようです) が、シングルコアのデバイスは 1 時間以上クラッシュしていません。

私は Apple にバグを報告しました。影響を受ける場合は、同じことを行うことをお勧めします。

于 2012-07-25T18:23:13.370 に答える
-1

UIKit がスレッド セーフだとは思いませんし、バックグラウンド スレッドからの描画は非常にファンキーです。うまくいくかもしれないし、うまくいかないかもしれない。

UIGraphicsBeginContext のドキュメントでは、実際にはメイン スレッドからのみ呼び出す必要があると明示的に述べています。明らかに、マルチスレッドは完全に検討の対象外です。

于 2012-07-21T05:41:41.423 に答える