2014-11-20 62 views
0

我收到此錯誤:NSArray countByEnumeratingWithState發送到解除分配的實例

沒有堆棧跟蹤。

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

什麼會調用這個方法?

是否可以確定這是什麼?我有殭屍,但沒有看到來電者。

這裏的線程1:

thread1 crash

唯一的其他可點擊行都是這樣從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:從Google分析中調用。一個項目找到&快開顯示沒有命名的選擇threadMain:

enter image description here

+0

當您在數組上進行快速枚舉時會調用這個函數。 – rdelmar 2014-11-20 22:36:53

+0

在for(myArray中的myobject * f)?我可以在項目中搜索哪些代碼以找到它? – quantumpotato 2014-11-20 22:37:58

+0

您是否添加了異常斷點以查看它是否確定了違規行? – rdelmar 2014-11-20 22:40:46

回答

1

(這是一個非常艱難一種錯誤的通過StackOverflow上進行調試,所以我只給指針在這裏。)

你幾乎肯定會修改多個線程上的一些數據結構。鑑於具體情況,我懷疑有一個數組是你在一個線程上放置的某個對象的一個​​ivar,而你正在其他線程上枚舉它。您可以通過釋放擁有的對象或通過替換數組來刪除它。

事實上,你打電話@synchronized(self)強烈建議你在這個程序中進行危險的線程。在現代的ObjC中,@synchronized幾乎從來都不是正確的工具。如果您直接使用NSThread,那可能也是您的麻煩來源(AFNetworking已經足夠大了,可以通過這個過程,但是您不應該複製它們的方法)。處理併發的正確工具是GCD(dispatch_*)或NSOperation

您是否驗證過self.contentDictionaryself.filePath的每個突變都是同步的。我特別懷疑self.contentDictionary,因爲它可能有數組。

在這裏正確使用訪問器的好處順便說一下,儘管如果它們不是原子的,如果你在不同的線程上讀寫它們,它們可能會在它們之間產生不一致的狀態。使它們成爲原子並不能完全保證線程安全;你仍然需要使用像GCD或NSOperation這樣的序列化訪問。

您調用@synchronized然後以相同方法發佈通知的事實也有些可疑。通知在它們發佈的同一個線程上同步處理,因此您的通知觀察者需要知道它們可能被調用的線程。

請注意,AFNetworking runloop處理方法中的崩潰是沒有意義的。這給你沒有真正的提示。

我會看你的線程。特別注意對數組的不受保護的訪問(特別是數組屬性)。並確保您使用GCD或NSOperation而不是@synchronize將所有訪問序列化。

+0

謝謝你的指點。當用戶登錄以獲取其配置文件數據時,會調用多個異步調度線程。我將調查應用程序中@synchronized的用法,並查看使用dispatch更新它的過程。 – quantumpotato 2014-11-21 21:54:04

+0

Rob,我確實看到一個threadMain:被Google Analytics調用。也許這就是所謂的NSThread?用堆棧跟蹤更新後。 – quantumpotato 2014-11-21 21:56:36

+0

你指的是什麼訪問器?在枚舉塊內? – quantumpotato 2014-11-21 22:06:02

相關問題