esi*_*ver 7 grand-central-dispatch sigabrt ios dispatch-async
我正在尝试调试我的许多用户在该领域报告的崩溃错误.所有都显示我相同的堆栈:
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)
Run Code Online (Sandbox Code Playgroud)
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: });
Run Code Online (Sandbox Code Playgroud)
虽然该块中肯定存在代码,但它只有1行长,并且该代码似乎不会在此堆栈上执行,否则我将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
Run Code Online (Sandbox Code Playgroud)
注意:有问题的对象是全局单例,如果愿意,我的"数据管理器".它处理网络请求并存储可能需要在UIViewControllers之间共享的状态.它最初声明如下:
+ (MyDataManager *)mainStore {
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)
我理解在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
Run Code Online (Sandbox Code Playgroud)
看起来问题出在对 的强引用上self,这会导致您的应用程序崩溃,显然是在调用self已释放的应用程序时。此代码将创建一个新变量,该变量将存储对 的弱引用self,这应该可以解决该问题:
__weak typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf cleanupMethod:args];
});
Run Code Online (Sandbox Code Playgroud)
有人会说你也必须__strong typeof(weakSelf)strongSelf = weakSelf;在这里使用,对弱引用进行强引用,以避免强引用循环但保持活动状态self,但我不想在这里这样做,self以防nil万一块的执行时间 - 消息nil在 Objective-C 中完全正常,所以不会发生任何事情。
加上该行之前发生的事情的堆栈跟踪
0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367)
Run Code Online (Sandbox Code Playgroud)
肯定有助于诊断问题。
mainStore编辑:嗯,您在访问共享对象时似乎没有使用类方法。也许这就是问题所在。
| 归档时间: |
|
| 查看次数: |
830 次 |
| 最近记录: |