Почему происходит сбой NSMutableDictionary setValue? - PullRequest
0 голосов
/ 18 мая 2018

setValue(_:forKey:) метод иногда падает.Наш NSMutableDictionary написан только из основного потока, но к нему часто обращаются.Может ли частый доступ к словарю вызвать сбой?

Я полагаю, что при Core Data изменение данных будет более надежным, но мы решили использовать постоянное хранилище на основе словаря.Есть ли способ сделать более надежный доступ к нашему NSMutableDictionary?

В любом случае, как я могу выяснить, какой метод setValue вылетает, если они выполняются в цикле?Если я напечатаю keyPath, конец цикла будет достигнут до того, как произойдет сбой, поэтому я не могу определить, какой именно вызов setValue вызовет сбой.

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Если я правильно понял, ваши настройки примерно такие: запись только в основном потоке, а чтение из других потоков.С этой настройкой:

let a = NSMutableDictionary()
let time = DispatchTime.now() + 0.01
DispatchQueue.global().asyncAfter(deadline: time) {
    for _ in 0..<10000000000000 {
        let b = self.a["\(self.a.count - 1)"]
        print(b)
    }
}

for index in 0..<1000000000000000 {
    a.setValue(NSNumber(value: index), forKey: "\(index)")
}

Я действительно смог воспроизвести вашу проблему.Вот трассировка стека, когда происходит сбой:

Thread 1 Queue : com.apple.main-thread (serial)
#0  0x00000001115286f6 in _kernelrpc_mach_vm_deallocate_trap ()
#1  0x0000000111530a43 in mach_vm_deallocate ()
#2  0x00000001112c8477 in mvm_deallocate_pages ()
#3  0x00000001112bfdc4 in free_large ()
#4  0x000000010cc5506b in mdict_rehashd ()
#5  0x000000010cac26c6 in -[__NSDictionaryM setObject:forKey:] ()
#6  0x000000010b9382f5 in ViewController.viewDidLoad() at 

Thread 5 Queue : com.apple.root.default-qos (concurrent)
#0  0x000000010cafc454 in -[__NSDictionaryM objectForKey:] ()
#1  0x000000010d11567b in NSMutableDictionary.subscript.getter ()
#2  0x000000010d115588 in @objc NSDictionary.subscript.getter ()
#3  0x000000010b93898d in closure #1 in ViewController.viewDidLoad() at 

Из освобождения в основном потоке, я думаю, setValue вызвал некоторую перебазирование в словаре, и в то время как чтение происходило одновременно, онопытается прочитать освобожденную память -> EXC_BAD_ACCESS.Подведение итогов: это должно быть проблемой параллелизма.

0 голосов
/ 18 мая 2018

Скорее проблема в другом месте.Попробуйте вместо этого установить точку останова на исключение.Таким образом, Xcode остановится, когда это произойдет.

В навигаторе точек останова выберите Exception breakpoint..., см. Рисунок ниже.

Обратите внимание, что вы можете остановиться и на других исключениях, если они обрабатываются, онине ошибки.В таком случае просто продолжайте работать.

enter image description here

...