При условии, что (пожалуйста, проверьте это)
_mySerialQueue
является переменной экземпляра _mySerialQueue
доступен только в @synchronized(self)
блоках - Вы не получаете доступ к
_mySerialQueue
через какое-либо свойство или кодировку значения ключа ([theObject valueForKey:"mySerialQueue"]
) - Весь код, который вы разместили, работает с ARC
Я вижу только одну причину, почемуприведенный выше код может привести к сбою, как это происходит.Я все еще не уверен на 100%, но вот мой выстрел:
self
находится в процессе освобождения, когда происходит сбой.Это можно проверить, если вы очистите iVar в dealloc
:
- (void)dealloc {
@synchronized(self) {
_mySerialQueue = nil;
}
// ...
}
, эти сбои будут крайне редкими, например, как минимум один из ста.Если это случается чаще, я думаю, что проблема в другом месте.
После изменения приложение все равно будет аварийно завершать работу, но EXC_BAD_ACCESS будет находиться в нижней области памяти, потому что вы разыменовываете нулевой указатель при вызовеdispatch_async(nil, ...)
.Место сбоя, скорее всего, будет 0x00000050 или аналогично низким адресом.
Почему я так думаю? Когда объект разрушается, iVars уничтожаются в отдельном проходеметод с именем .cxx_destruct
.Когда это происходит, iVar может быть в процессе освобождения, но в то же время переменная все еще указывает на объект, потому что он никогда не очищается.
Важно: Если это работает, он просто заменит один редкий сбой на другой редкий сбой, потому что это будет означать, что где-то есть условие гонки self
.
Другое возможное решение - попытаться воспроизвести проблему с дезинфицирующее средство для нитей .В большинстве случаев он может довольно быстро отследить такие проблемы.