我正在尝试调试我的许多用户在这个领域中报告的一个崩溃错误。所有给我看的都是同一个堆栈:
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行长,并且该代码似乎没有在这个堆栈上执行,因为否则我会在cleanupMethod上看到myMethod。
编辑:您可以看到,就在dispatch_async之前,有一个断言!我原本以为这次坠机是由于断言。但是行号从来没有匹配--断言更高一些(第2364行,而不是2367行) --当我进一步测试它时,我发现如果断言被触发,我的堆栈将不包括您可以看到的_block_invoke,您可以在调用myMethod的末尾看到它。
有人能建议dispatch_async如何触发这种行为吗?此外,我有没有办法用libsystem_c.dylib来象征苹果的代码呢?
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方法是called...but时,我理解被解除分配对象的后果--我曾经认为我的全局单例总是存在的,因此在代码中调用的方式总是安全的。此外,我不关心保留周期,因为再次,这应该是一个全球性的单例。
下面的代码示例可以做吗?
@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发布于 2015-10-25 11:38:21
看起来问题就在对self的强烈引用中,它使您的应用程序崩溃,显然是在调用已被取消分配的self时。这段代码将生成一个新变量,它将存储弱引用到self,这将解决这个问题:
__weak typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf cleanupMethod:args];
});有些人可能会说,您必须在这里使用__strong typeof(weakSelf)strongSelf = weakSelf;,对弱引用进行强引用,避免强引用循环,但使self保持活力,但我不希望在这里这样做,如果在执行块时self将成为nil,那么给nil的消息在目标-c中是非常好的,所以不会发生任何事情。
加上行之前发生的事情的堆栈跟踪。
0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367)肯定会有助于诊断一个问题。
编辑:在访问共享对象时,您似乎不使用类方法mainStore。也许这就是问题所在。
https://stackoverflow.com/questions/33326860
复制相似问题