2010-05-31 4 views
0

Пользователь отправил отчет о сбое со следами стека, перечисленными ниже (я не смог воспроизвести сам аварий, но каждый другой крах, который этот пользователь сообщил, был действительной ошибкой, даже если я не смог воспроизвести эффект). Приложение представляет собой приложение Objective-C/Cocoa с подсчетом ссылок.Представитель NSDrawer, указывающий на освобожденный объект?

Если я правильно его интерпретирую, авария вызвана попыткой отправить сообщение drawerDidOpen: освобожденному объекту. Единственным объектом, который должен получать drawerDidOpen:, является объект-делегат ящика (нигде не регистрируется какой-либо объектный регистр для получения уведомлений о выдвижном ящике), а объект-делегат ящика создается через файл XIB/NIB, подключенный к выходу делегата ящика, а не ссылки на другие места.

Учитывая, что, как я могу защитить от делегирования делегата, который должен быть удален до уведомления ящика? Или, поочередно, что я неверно истолковал, что может вызвать крушение?

журнала Краш/трассировки стека:

Exception Type: EXC_BAD_ACCESS (SIGSEGV) 
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010 
Crashed Thread: 0 Dispatch queue: com.apple.main-thread 

Application Specific Information: 
objc_msgSend() selector name: drawerDidOpen: 

Thread 0 Crashed: Dispatch queue: com.apple.main-thread 
0 libobjc.A.dylib     0x00007fff8272011c objc_msgSend + 40 
1 com.apple.Foundation   0x00007fff87d0786e _nsnote_callback + 167 
2 com.apple.CoreFoundation  0x00007fff831bcaea __CFXNotificationPost + 954 
3 com.apple.CoreFoundation  0x00007fff831a9098 _CFXNotificationPostNotification + 200 
4 com.apple.Foundation   0x00007fff87cfe7d8 -[NSNotificationCenter postNotificationName:object:userInfo:] + 101 
5 com.apple.AppKit    0x00007fff8512e944 _NSDrawerObserverCallBack + 840 
6 com.apple.CoreFoundation  0x00007fff831d40d7 __CFRunLoopDoObservers + 519 
7 com.apple.CoreFoundation  0x00007fff831af8c4 CFRunLoopRunSpecific + 548 
8 com.apple.HIToolbox    0x00007fff839b8ada RunCurrentEventLoopInMode + 333 
9 com.apple.HIToolbox    0x00007fff839b883d ReceiveNextEventCommon + 148 
10 com.apple.HIToolbox    0x00007fff839b8798 BlockUntilNextEventMatchingListInMode + 59 
11 com.apple.AppKit    0x00007fff84de8a2a _DPSNextEvent + 708 
12 com.apple.AppKit    0x00007fff84de8379 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155 
13 com.apple.AppKit    0x00007fff84dae05b -[NSApplication run] + 395 
14 com.apple.AppKit    0x00007fff84da6d7c NSApplicationMain + 364 
15 (my app's identifier)   0x0000000100001188 start + 52 

редактировать: Для уточнения: Это крушение случилось один раз в тысячи или, возможно, десятки тысяч практически идентичных сценариев использования. Я не сохраняю/release/alloc/dealloc/anything-memory-management объект делегирования в любом месте моего кода; Я не регистрирую какой-либо объект для каких-либо уведомлений любого ящика в моем коде; мой код не имеет переменных (или ivars), указывающих на объект делегата.

Что мне кажется, что когда NIB был выгружен (как в случае системы Cocoa, когда окно документа закрывается), каким-то образом объект-делегат ящика был удален до самого объекта ящика, но Предполагается, что система какао предотвратит это (и, кажется, правильно ее обрабатывает в подавляющем большинстве случаев).

+0

Вы видите 'KERN_INVALID_ADDRESS на 0x0000000000000010'? Это, скорее всего, означает, что ваша программа думала, что делегат там. Что, очевидно, не так. – zneak

+0

Правильно, ясно. Вопрос в том, почему * не был там делегатом? – Isaac

ответ

1

Делегат был освобожден до освобождения без предварительного уведомления из центра уведомлений (в этом случае делегация проходит через центр уведомлений, а не напрямую).

Простым решением является вызов метода NSNotificationCenter's-removeObserver: из вашего метода -dealloc вашего делегата.


Проверьте обратную линию - через центр уведомлений произошел сбой. Скорее всего, когда класс подключен через setDelegate: (через файл NIB), это делается как наблюдатель уведомлений.

Независимо от того, что связь между центром уведомлений и вашим объектом такая же, как между объектом в IB и вашим объектом; слабый. То есть, нет retain, и, таким образом, ваш делегат освобождается слишком рано (или, альтернативно, вы перевыпускаете объект где-то).

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

+0

Если делегат регистрировался через 'NSNotificationCenter', я бы понял (и на самом деле я дважды проверял все экземпляры NSNotificationCenter, регистрируя уведомление о выдвижном ящике), но делегат только создается в NIB и только ссылается на делегат' IBOutlet' на 'NSDrawer', то есть единственный способ получить указатель на объект делегата в моем коде, как есть, будет через' [theDrawerObjectOfSomeWindow delegate] '. – Isaac

+0

Что касается центра обратной связи/уведомления, да, он проходит через центр уведомлений, но, поскольку я не просил наблюдать, мне не нужно было бы удалять наблюдателя (т. Е. Если регистрация скрыта от меня, удаление регистрации должно быть скрыто , слишком). Per http://developer.apple.com/mac/library/documentation/cocoa/conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6 объекты верхнего уровня, созданные в NIB имеет счет сохранения 1 в среде с подсчетом ссылок, поэтому я не понимаю, почему/как объект делегата получает dealloc'd. – Isaac

+0

Как ни странно, в то время как цитируемые документы говорят, что я должен выпустить объекты верхнего уровня, созданные в NIB, «Build and Analyze» обозначает выпуск как ошибку. – Isaac

Смежные вопросы