NSDrawer делегат, указывающий на освобожденный объект? - PullRequest
0 голосов
/ 31 мая 2010

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

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

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

Журнал аварий / трассировка стека:

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

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

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

1 Ответ

1 голос
/ 01 июня 2010

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

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

<Ч />

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...