首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么能在iOS9.1中的dispatch_async上触发SIGABRT?

什么能在iOS9.1中的dispatch_async上触发SIGABRT?
EN

Stack Overflow用户
提问于 2015-10-25 06:25:42
回答 1查看 949关注 0票数 7

我正在尝试调试我的许多用户在这个领域中报告的一个崩溃错误。所有给我看的都是同一个堆栈:

代码语言:javascript
复制
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行简单如下:

代码语言:javascript
复制
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的二进制图像:

代码语言:javascript
复制
0x3921a000 - 0x3927efff libsystem_c.dylib armv7  <0b5d65608e6f38448cd207fbd748d372> /usr/lib/system/libsystem_c.dylib

注意:所讨论的对象是全局单例,如果您愿意的话,是我的“数据管理器”。它处理网络请求并存储可能需要在UIViewControllers之间共享的状态。它最初宣布如下:

代码语言:javascript
复制
+ (MyDataManager *)mainStore {
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

当我的cleanupMethod:args方法是called...but时,我理解被解除分配对象的后果--我曾经认为我的全局单例总是存在的,因此在代码中调用的方式总是安全的。此外,我不关心保留周期,因为再次,这应该是一个全球性的单例。

下面的代码示例可以做吗?

代码语言:javascript
复制
@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
EN

回答 1

Stack Overflow用户

发布于 2015-10-25 11:38:21

看起来问题就在对self的强烈引用中,它使您的应用程序崩溃,显然是在调用已被取消分配的self时。这段代码将生成一个新变量,它将存储引用到self,这将解决这个问题:

代码语言:javascript
复制
__weak typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    [weakSelf cleanupMethod:args];
});

有些人可能会说,您必须在这里使用__strong typeof(weakSelf)strongSelf = weakSelf;,对弱引用进行强引用,避免强引用循环,但使self保持活力,但我不希望在这里这样做,如果在执行块时self将成为nil,那么给nil的消息在目标-c中是非常好的,所以不会发生任何事情。

加上行之前发生的事情的堆栈跟踪。

代码语言:javascript
复制
0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367)

肯定会有助于诊断一个问题。

编辑:在访问共享对象时,您似乎不使用类方法mainStore。也许这就是问题所在。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33326860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档