Я получаю отчеты о сбоях (через отличный Hockey), указывающие на то, что у меня проблема с памятью в каком-то коде, который вызывается внутри блок dispatch_sync
(по крайней мере, так я интерпретирую приведенный ниже фрагмент отчета о сбое). Мне вообще не удалось воссоздать этот сбой на моих тестовых устройствах (поэтому такие стратегии, как NSZombieEnabled
, мне не помогают). Я рад внести изменения в код, чтобы сделать отчеты о сбоях более информативными (и в конечном итоге решить основную проблему), я просто не знаю, с чего начать. Какие-нибудь мысли?
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0xb000000c
Crashed Thread: 7
...
Thread 7 Crashed:
0 libobjc.A.dylib 0x3979bb66 _objc_msgSend + 6
1 libdispatch.dylib 0x39c898fb _dispatch_barrier_sync_f_invoke + 27
2 App 0x00260f23 __48-[Foo displayLinkCallback]_block_invoke + 147
3 libdispatch.dylib 0x39c85103 _dispatch_call_block_and_release + 11
4 libdispatch.dylib 0x39c894bf _dispatch_async_redirect_invoke + 111
5 libdispatch.dylib 0x39c8a7e5 _dispatch_root_queue_drain + 225
6 libdispatch.dylib 0x39c8a9d1 _dispatch_worker_thread2 + 57
7 libsystem_pthread.dylib 0x39db4dff __pthread_wqthread + 299
dispatch_sync
предоставляется статическая последовательная очередь. Возможно ли, что _objc_msgSend
указывает на проблему со ссылкой на эту очередь, а не на проблему внутри блока?
Чтобы предвосхитить очевидное, я не вижу в этих отчетах о сбоях указаний на тупиковые ситуации.
Обновление (8 октября 2013 г.)
Добавление кода в соответствии с запросом (имена методов и переменных изменены, но все еще близки к оригиналу). Я подозреваю, что проблема где-то в копировании foo
. Я надеялся, что этот вопрос даст стратегии для отладки этой ошибки. Если «проверка построчно» — лучшая стратегия для отладки _objc_msgSend
сбоев внутри блока dispatch_sync
, то это немного грустно, но я приму любую помощь, которую смогу получить на этом этапе.
Кроме того, я должен отметить, что сбой, который я расследую, происходит только на одноядерных устройствах, и то с перерывами.
- (void) displayLinkCallback
{
dispatch_async(_frameDispatchQueue, ^{
if ([_lock tryLock])
{
dispatch_sync(_renderQueueSerial, ^{
NSObject *fooCopy = nil;
BOOL bar = NO;
// prevents deallocation during subsequent copy
// _foo is set and/or its child objects changed
// many times per second by other threads)
NSObject *foo = _foo;
// copy foo
fooCopy = [foo copy];
bar = [self needsBarGivenFoo:fooCopy];
if (bar)
{
_lastFoo = foo;
[self goFoo:fooCopy];
}
else
{
[self noFoo:fooCopy];
}
});
[_lock unlock];
}
});
}