使用NSOperationQueue进行的Crashlytics崩溃(QOS:未评论) [英] Crashlytics Crash with NSOperationQueue (QOS: UNSPECIFIED)

查看:67
本文介绍了使用NSOperationQueue进行的Crashlytics崩溃(QOS:未评论)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Crashlytics中报告崩溃,并且我不知道如何重现该错误,它是随机发生的,因此很难使用Xcode对其进行调试.有什么想法吗?

I'm getting a crash, reported in Crashlytics, and I have no idea how to reproduce the error, It happens randomly so it's hard to debug it with Xcode. Any ideas?

Crashed: NSOperationQueue 0x280419200 (QOS: UNSPECIFIED)
0 libobjc.A.dylib 0x22c471430 objc_retain + 16
1 CoreFoundation 0x22d2b5888 __CFBasicHashAddValue + 1480
2 CoreFoundation 0x22d1e64ac CFDictionarySetValue + 260
3 Foundation 0x22dd04888 _encodeObject + 732
4 myAPI 0x1062b44b0 -[DataCore encodeWithCoder:] (DataCore.m:236)
5 myAPI 0x1062909c4 -[DataHandle encodeWithCoder:] (DataHandle.m:53)
6 Foundation 0x22dd04aa8 _encodeObject + 1276
7 Foundation 0x22dc69c6c +[NSKeyedArchiver archivedDataWithRootObject:] + 168
8 myAPI 0x106288a34 __77+[CachableObject addObjectToCache:withCacheName:withTTL:withCompletionBlock:]_block_invoke (CachableObject.m:162)
9 Foundation 0x22dd198bc NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK + 16
10 Foundation 0x22dc21ab8 -[NSBlockOperation main] + 72
11 Foundation 0x22dc20f8c -[__NSOperationInternal _start:] + 740
12 Foundation 0x22dd1b790 __NSOQSchedule_f + 272
13 libdispatch.dylib 0x22ccc16c8 _dispatch_call_block_and_release + 24
14 libdispatch.dylib 0x22ccc2484 _dispatch_client_callout + 16
15 libdispatch.dylib 0x22cc6582c _dispatch_continuation_pop$VARIANT$mp + 412
16 libdispatch.dylib 0x22cc64ef4 _dispatch_async_redirect_invoke + 600
17 libdispatch.dylib 0x22cc71a18 _dispatch_root_queue_drain + 376
18 libdispatch.dylib 0x22cc722c0 _dispatch_worker_thread2 + 128
19 libsystem_pthread.dylib 0x22cea517c _pthread_wqthread + 472
20 libsystem_pthread.dylib 0x22cea7cec start_wqthread + 4

这是DataCore.m中的代码的样子

Here is what the code in DataCore.m looks like

- (void)encodeWithCoder:(NSCoder *)coder {
    [super encodeWithCoder:coder];
    [coder encodeObject:programFormatPlayInfo forKey:@"ProgramFormatPlayInfo"];
    [coder encodeObject:bigScreenPlayInfo forKey:@"BigScreenPlayInfo"];
    [coder encodeObject:pivotHandle forKey:@"PivotHandle"];
    [coder encodeInteger:pivotDataLinkId forKey:@"PivotDataLinkId"];
    [coder encodeInteger:viewContextId forKey:@"ViewContextId"];
    [coder encodeBool:suppressImagePivot forKey:@"SuppressImagePivot"];
    [coder encodeObject:attributeIds forKey:@"AttributeIds"];
    [coder encodeObject:self.overflow forKey:@"Overflow"];
    [coder encodeObject:self.cacheNameWithUser forKey:@"CacheNameWithUser"];
    [coder encodeObject:self.metaData forKey:@"Metadata"];
}

,这是我尝试将对象添加到缓存的地方,不知道它是否解码失败或与后台队列有关.

and here is where I try to add an object to the cache, not sure if it's failing to decode or something related to the background queue.

+ (void)addObjectToCache:(CachableObject*)object withCacheName:(NSString*)cacheName withTTL:(CacheTime)cacheTimeSeconds withCompletionBlock:(void(^)()) block {
    CachableObject* theObject = object;
    [_backgroundQueue addOperationWithBlock:^{
        @autoreleasepool {
            @try {
                NSString * path = [CachableObject pathForCachedObject:cacheName];
                NSDate * date = [NSDate date];

                [object setCacheDate:date];
                [object setTtlSeconds:[NSNumber numberWithInteger:cacheTimeSeconds]];
                [object setApiVersion:APIVERSION];

                // Add to NSCache
                [[CachableObject objectCache] setObject:theObject forKey:cacheName];

                // Add to file system
                NSError* err = nil;
                NSData * data = [NSKeyedArchiver archivedDataWithRootObject:theObject];
                if (data) {
                    [data writeToFile:path options:NSDataWritingAtomic error:&err];
                }

                // Add to dynamic cache
                unwrapObjectAndComplyWithClass(object, [DataHandle class], ^(id unwrappedObject) {
                    DataHandle *objectUnwrapped = unwrappedObject;
                    DataFrame *objectFrame = objectUnwrapped.frame;
                    for (NSString *eachDependencyName in objectFrame.dependencies) {
                        [[VVIDynamicCacheManager sharedManager]addDependencyToStore:eachDependencyName withCacheName:cacheName];
                    }
                }, ^{
                   /*Not a data handle*/
                });

            } @catch (NSException* ex) {
                NSLog(@"CachableObject: got an exception %@", ex);
            } @finally {
                if (block) {
                    block();
                }
            }
        }
    }];
}

推荐答案

这里有些想法.

首先,您正在使用@ try/@ catch.我相信 NSKeyedArchiver 在应实际返回 NSError 对象时会引发异常.因此,也许这就是您这样做的原因.但是,您必须记住,不能保证没有苹果框架是例外-安全.这意味着捕获异常会导致Apple的代码(当然还有您自己的代码)处于不一致的状态,这将阻止它在将来正常工作.

First, you're using @try/@catch. I believe that NSKeyedArchiver throws exceptions when it should actually return NSError objects. So, perhaps that's why you are doing it. But, you have to keep in mind that none of Apple's frameworks are guaranteed to be exception-safe. This means that catching exceptions can leave Apple's code (and, of course, your own) in inconsistent states that will prevent it from working correctly in the future.

我强烈建议您删除@catch,或者在 NSKeyedArchiver 代码周围进行非常严格的范围设置,如果这就是您使用它的原因.这可能是无意中向您的应用程序引入了许多其他错误.

I would strongly recommend either removing the @catch, or scoping it extremely tightly around the NSKeyedArchiver code, if that's why you are using it. This could be unintentionally introducing a variety of other bugs into your app.

现在,继续进行特定的崩溃.它发生在运行时的内存管理代码中.这非常强烈地指出了堆损坏.这意味着您在内存中没有指向有效的Objective-C对象的指针.发生这种情况的原因可能很多,并且极端很常见.最常见的原因是悬空指针.但是,它也可能是由于释放过多而引起的.而且,如果可以使用@catch触发过度释放,我也不会感到惊讶.(我知道,我在竖琴,但是我已经看到如此由该模式引起的许多问题)

Now, on to the specific crash. It's occurring in the runtime's memory management code. This points very strongly at heap corruption. This means you've got a pointer that doesn't point to a valid Objective-C object in memory. This can happen for many reasons, and is extremely common. The most common cause is known as a dangling pointer. However, it could also be caused by an over-release. And, I wouldn't be at all surprised if it is possible to use an @catch to trigger an over-release. (I know, I'm harping, but I've seen so many issues caused by this pattern)

在这些情况下,我通常建议:

What I generally recommend in these situations:

  • 寻找其他与堆腐败相关的崩溃
  • 在Instruments中尝试 Zombies (僵尸)
  • 尝试使用malloc scribble或guardmalloc,这是另外两个不错的内存调试工具

很难(甚至通常不可能)推断堆损坏.复制该错误也可能是不可能的,因为内存损坏通常不是确定性的.

It's hard, and often even impossible, to reason about heap corruption. Replicating the bug can also be impossible, as memory corruption is typically not deterministic.

因此,只需尝试查找并修复尽可能多的问题.完全有可能其中之一是导致各种崩溃的原因,其中之一可能就是这种崩溃.

So, just try to find and fix as many issues as you can. It's totally possible that one of them is responsible for a variety of crashes, one of which could be this one.

这篇关于使用NSOperationQueue进行的Crashlytics崩溃(QOS:未评论)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆