私は現場の多くのユーザーから報告されたクラッシュするバグをデバッグしようとしています。iOS9.1のdispatch_asyncでSIGABRTをトリガできる原因は何ですか?
2363: BOOL success = [db executeUpdate:@"INSERT INTO table (id, content) VALUES (?, ?)", message.remoteId, message.content];
2364: assert(success);
2365: DebugLog(@"DB Results %d", success);
2366:
2367: dispatch_async(dispatch_get_main_queue(), ^{
2368: [self cleanupMethod:args];
2369: });
確かにそのブロック内のコードがあるが、それは唯一の1行の長だし、そのコードが実行されるように表示されません。
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 8
OS Version: iOS 9.1 (13B143)
Code Type: ARM (Native)
0 libsystem_kernel.dylib 0x392ccc84 0x392b8000 + 85124
1 libsystem_pthread.dylib 0x39370732 0x3936c000 + 18226
2 libsystem_c.dylib 0x39264f9a 0x3921a000 + 307098
3 libsystem_c.dylib 0x39264f2c 0x3921a000 + 306988
4 libsystem_c.dylib 0x392447ea 0x3921a000 + 174058
5 MyApp 0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367)
ライン2367は単純です:すべては私に同じスタックを表示しますそうでなければ私はcleanupMethod
の上にmyMethod
を見るでしょう。
編集:dispatch_asyncの直前に、アサートがあることがわかります!私はもともと、このクラッシュが主張に起因すると考えていました。しかし、行番号は一度も一致しませんでした。つまり、アサーションは多くの行が上にあります(行2364ではなく2367)。さらにテストしたところ、アサートがトリガーされた場合、スタックには_block_invoke
myMethodの呼び出しの最後に追加されることがあります。
どのようにdispatch_asyncがこの動作を引き起こす可能性がありますか?さらに、libsystem_c.dylibでAppleのコードを象徴する方法はありますか? libsystem_c.dylibの
バイナリイメージ:
0x3921a000 - 0x3927efff libsystem_c.dylib armv7 <0b5d65608e6f38448cd207fbd748d372> /usr/lib/system/libsystem_c.dylib
注:あなたがする場合は問題のオブジェクトがグローバルシングルトン、私の "データ管理" です。ネットワーク要求を処理し、UIViewController間で共有する必要のある状態を格納します。これは次のようにもともと宣言されています:
+ (MyDataManager *)mainStore {
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
私は私のcleanupMethod:args
メソッドが呼び出されたときに割り当て解除されているオブジェクトの結果を理解...しかし、私はは私のグローバルシングルトンは、常に周りので、常に安全になりと思っていました自分のコードでやり取りする方法で呼び出しますか?私はさらに、今度はグローバルシングルトンであると考えられて以来、保持サイクルについて心配していません。
このコードサンプルは次のとおりですか?
@interface MyDataManager
@end
@implementation MyDataManager
+ (MyDataManager *)mainStore {
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void)myMethod {
NSDictionary *args = @{...}
...
dispatch_async(dispatch_get_main_queue(), ^{
[self cleanupMethod:args];
});
}
- (void)cleanupMethod:(id)args {
...
}
@end
@interface MyViewController : UIViewController
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[MyDataManager sharedInstance] myMethod];
}
@end
質問を編集してブロックの内容を含めるか、少なくともMyDataManager.mの2367行の次の行を含めると役立ちます。 –
@rob mayoff完了! – esilver
ブロックがトリガされた時点で 'self'のように見えなくなったようです。 –