0

我收到此错误:

没有堆栈跟踪。

-[__NSArrayI countByEnumeratingWithState:objects:count:]: message sent to deallocated instance

什么叫这个方法?

有没有可能确定这叫什么?我有僵尸,但没有看到来电者。

这是线程1:

线程 1 崩溃

其他唯一可点击的行是来自 AFNetworking ( [runloop run]) 的行。我刚刚升级了我的 AFNetworking 吊舱。

+ (void)networkRequestThreadEntryPoint:(id)__unused object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"AFNetworking"];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
}

编辑:上面的断点@autoreleasepool甚至没有被命中。我确实在另一个线程中的同一崩溃的代码中找到了这个(上次没有看到):,在archiveSuccessful = line

- (void)archiveContent:(BOOL)changeNotification userInfo:(NSDictionary *)userInfo {
    BOOL archiveSuccessful;
    @synchronized(self) {
        archiveSuccessful = [NSKeyedArchiver archiveRootObject:self.contentDictionary toFile:self.filePath];
    }
    if (archiveSuccessful) {
        if(changeNotification && self.contentChangedNotificationName) {
            [[NSNotificationCenter defaultCenter] postNotificationName:self.contentChangedNotificationName object:nil userInfo:userInfo];
        }
    } else {
        NSAssert(NO, @"Saving archive to %@ was not successful", self.filePath);
    }
}

这被称为

- (void)addObjects:(NSArray *)objects changeNotification:(BOOL)changeNotification {
    [objects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if([obj conformsToProtocol:NSProtocolFromString(@"DRLocalObject")]) {
            [self addObject:obj changeNotification:NO];
        }
    }];

调试器打印[self addObject...输出

(lldb) po obj
0x00007fde0ff56770

(lldb) po 0x00007fde0ff56770
140591727208304

编辑:

threadMain:从谷歌分析调用。项目查找和快速打开显示没有命名选择器threadMain:

在此处输入图像描述

4

1 回答 1

1

(这是一种很难通过 StackOverflow 调试的错误,所以我只是在这里给出指点。)

您几乎可以肯定正在修改多个线程上的某些数据结构。鉴于具体情况,我怀疑有一个数组是某个对象的 ivar,当您在其他线程上枚举它时,您将其放在一个线程上。您可以通过解除分配拥有的对象或替换数组来删除它。

您正在调用的事实@synchronized(self)强烈表明您在该程序中执行危险的线程。在现代 ObjC 中,@synchronized几乎从来都不是正确的工具。如果你NSThread直接使用,那可能也是你麻烦的一个来源(AFNetworking 已经足够老了,可以通过这个,但你不应该复制他们的方法)。处理并发的正确工具是 GCD( dispatch_*) 或NSOperation.

您是否验证过 和 的每个突变self.contentDictionary也是self.filePath同步的。我会特别怀疑,self.contentDictionary因为它是那种可能有数组的东西。

顺便说一句,在这里正确使用访问器值得称赞,但如果它们不是原子的,如果您在不同的线程上读取和写入它们,则可能会在它们上获得不一致的状态。使它们原子化并不能使它们完全线程安全;您仍然确实需要使用 GCD 之类的东西或NSOperation序列化访问。

@synchronized您打电话然后以相同方法发布通知的事实也有些可疑。通知在发布它们的同一线程上同步处理,因此您的通知观察者需要知道它们可能在哪个线程上被调用。

注意 AFNetworking runloop 处理方法中的 crash 是没有意义的。这没有给你任何真正的暗示。

我会看你的线程。特别注意对数组(尤其是数组属性)的未受保护访问。并确保使用 GCD 序列化所有访问NSOperation,而不是@synchronize.

于 2014-11-21T21:23:13.247 回答