我正在尝试调试一些用户在现场报告的崩溃错误。所有的报告都显示相同的堆栈:
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之前有一个assert!最初,我认为这个崩溃是由于assert引起的。但是行号从未匹配 - assert的行号很高(第2364行,而不是第2367行) - 并且当我进一步测试时,我发现如果触发了assert,我的堆栈将不包括您可以看到附加到对myMethod的调用末尾的_block_invoke
。
有人能建议我如何触发此行为的dispatch_async吗?此外,是否有任何方法可以符号化libsystem_c.dylib中的Apple代码?
libsystem_c.dylib的二进制映像:
0x3921a000 - 0x3927efff libsystem_c.dylib armv7 <0b5d65608e6f38448cd207fbd748d372> /usr/lib/system/libsystem_c.dylib
注意:在这里讨论的对象是一个全局单例,相当于我的“数据管理器”。它处理网络请求并存储可能需要在UIViewControllers之间共享的状态。最初声明的方式如下:
+ (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
self
的证据,该块应该对self
有一个强引用,从而防止其被释放。 - rob mayoffiOS 9.0.2 (13A452)
。代码类型是什么?例如ARM-64 (Native)
。libsystem_c.dylib
的二进制映像在文件末尾附近列出了什么?例如0x199098000 - 0x199118fff libsystem_c.dylib arm64 <5052939437823b09a7b068807808eff2> /usr/lib/system/libsystem_c.dylib
。 - rob mayoff