Reputation: 35114
setValue(_:forKey:)
method crashes sometimes. Our NSMutableDictionary
is written only from main thread, but it is often accessed. Can frequent access of dictionary cause a crash?
I guess with Core Data
changing data would be more robost, but we decided to use dictionary based persistent storage. Is it any way to make more reliable accessing our NSMutableDictionary
?
Anyway how could I figure out which setValue
method crash if they are executed in a loop? If I print keyPath
, end of loop will be reached before the crash happen, so I can not narrow down which setValue
call exactly cause the crash.
Upvotes: 1
Views: 2084
Reputation: 12045
If I understood it correctly, your setup is something like this: writing only on the main thread but reading from another threads. With this setup:
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)")
}
I was indeed able to reproduce your issue. Here is the stack trace when the crash is happening:
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
From the deallocations on the main thread I guess setValue
caused some rebucketing on the dictionary, and as a reading happening at the same time, it tries to read deallocated memory -> EXC_BAD_ACCESS
.
Wrapping up: this should be a concurrency issue.
Upvotes: 1
Reputation: 4333
It is more likely the problem elsewhere. Try setting a breakpoint on exception instead. That way Xcode will stop when it happens.
In the breakpoint navigator choose Exception breakpoint...
, see picture below.
Note that you might stop at other exceptions too, if they are handled they are not errors. In such case, just continue running.
Upvotes: 0