【发布时间】:2016-01-24 10:29:54
【问题描述】:
我正在尝试调试我的许多用户在该领域报告的崩溃错误。都给我看相同的堆栈:
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 行很简单:
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 行长,并且该代码似乎不会在此堆栈上执行,否则我会在 myMethod 上方看到 cleanupMethod。
编辑:您可以看到,就在 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 行之后的几行,这将有所帮助。
-
好像你的
self在块被触发时被释放 -
由于没有
self的特殊声明,因此该块应该具有对self的强引用,从而防止它被释放。 -
崩溃报告中的操作系统版本是什么(文件顶部附近)?例如。
iOS 9.0.2 (13A452)。什么是代码类型?例如。ARM-64 (Native)。为libsystem_c.dylib(接近文件末尾)列出的二进制图像是什么?例如。0x199098000 - 0x199118fff libsystem_c.dylib arm64 <5052939437823b09a7b068807808eff2> /usr/lib/system/libsystem_c.dylib -
这只是我的猜测,您可以从仪器启用
zombie并检查实际发生的情况。
标签: ios grand-central-dispatch sigabrt dispatch-async