При каких условиях объект может измениться по адресу? (OBJ-с) - PullRequest
0 голосов
/ 01 октября 2009

У меня есть контроллер с делегатом.

@interface MyConversionController : NSObject {
    id <ConversionDelegate> _delegate;
}
@property (assign) id delegate;
@end    

@implementation
@synthesize delegate = _delegate;
@end

Я получаю Unrecognized selector sent to instance 0x36c4a0 ошибки. Я установил точку останова на методе -(void)setDelegate(id)delegate, чтобы я мог наблюдать объекты, которые передаются в мой класс MyConversionController. Мой setDelegate метод вызывается дважды, в первый раз это объект по адресу 0x36c4a0, который, как я знаю, соответствует протоколу <ConversionDelegate>. Во второй раз, когда этот метод вызывается, передается другой объект, который также соответствует протоколу. Когда приходит время начать вызывать методы делегата, вызовы метода отправляются первому объекту (0x36c4a0), который теперь является объектом другого типа (обычно это CFString или __NSFastEnumerationEnumerator, если это имеет значение).

Кто-нибудь знает, почему это может происходить?


После запуска malloc_history я вижу, что первый адрес, тот, который доставляет мне проблемы, выделяется и освобождается несколько раз, прежде чем я доберусь до него. Второй объект просто выделяется один раз. При каких условиях указатели будут повторно использоваться таким образом?

Ответы [ 2 ]

1 голос
/ 01 октября 2009

Возможно, вы захотите использовать malloc_history, чтобы найти стек вызовов объекта по этому адресу. Во время работы вашего процесса выполните следующие действия в терминале:

malloc_history <pid> 0x36c4a0 # insert the address in question for the 2nd arg

Вам также необходимо включить MallocStackLogging (благодаря комментарию Куби, приведенному ниже).

Это может помочь вам понять, где находится объект по этому адресу.


Кроме того, вы отметили делегата как назначить, а не сохранить, однако, я думаю, что это подходит для делегатов. Тем не менее, если он был автоматически выпущен где-то еще, эта память может быть повторно использована.

Возможно, вы автоматически высвобождаете делегата и назначаете его? Что-то вроде:

delegate = [[[ConversionDelegateClass alloc] init] autorelease];
controller.delegate = delegate

Если это так, делегат будет освобожден в следующем выпуске автоматического пула, поскольку ничто его не хранит, и это место в памяти будет доступно для повторного использования.

0 голосов
/ 06 октября 2009

Проблема в том, что делегат был преждевременно освобожден. Причина, по которой это было так трудно отлаживать, заключалась в том, что освобождение произошло в коде, который я написал давно, и программа закрылась до того, как возникнут проблемы. При написании нового фрагмента кода программа оставалась открытой достаточно долго, чтобы другие классы могли начать отправлять сообщения освобожденному объекту.

Решение: Я запустил код с модулем Zombie в Инструментах. Жаль, что я сделал это несколько дней назад, я исправил код в течение 30 секунд после просмотра вывода инструментов.

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