EXC_BAD_ACCESS при обмене сообщениями действительного объекта - PullRequest
1 голос
/ 31 августа 2011

Мой главный контроллер приложения вызывает субконтроллер для обработки определенной последовательности экранов. Главный контроллер устанавливает себя как делегат в субконтроллере. Когда субконтроллер делает свое дело, он уведомляет делегата. Время от времени это уведомление завершается с ошибкой EXC_BAD_ACCESS.

0) В зависимости от gdb проблема возникает в objc_msgSend. Оба регистра имеют ненулевое значение.

gdb: 0x3367cc98  <+0016>  ldr   r5, [r4, #8]

1) Я пытался отследить проблему с помощью NSZombiesEnabled, но потом не смог ее воспроизвести. 2) Я пытался установить точку останова непосредственно перед проблемной командой, но снова не могу воспроизвести проблему.

Понятия не имею, что происходит.

Это объявление свойства делегата (родительский контроллер переживает дочерний элемент):

@property (assign) id<ParentControllerDelegate> delegate

Это проблемный код:

- (void) doStuff {
   if(mode == Done) {
     NSLog(@"Done. Handling back control");//this is the last log displayed by the console
     [self.delegate done: self];
   } else {
     // some controller code
}

Это код на стороне делегата (делегат был сохранен в App_Delegate, поскольку он является главным контроллером).

- (void) done: (UIViewController *) caller {
   NSLog(@"Taken back control");// this never displays
   [caller.view removeFromSuperview];
   [caller release];
}

Дополнительная информация: Главный контроллер сохраняет субконтроллер. Я также изменил dealloc в главном и вспомогательном контроллерах, чтобы он регистрировался при его вызове. Судя по видимым журналам, ни один из них никогда не вызывается в течение приложения. Следовательно, и получатель, и отправитель сообщения являются действительными объектами.

Я действительно в недоумении. Ждем вашей помощи.

Ответы [ 3 ]

0 голосов
/ 31 августа 2011

Если вызов NSLog в done: никогда не выполняется, это может означать, что вы не вызывали done: главного контроллера.Это может означать, что self.delegate недействительно.Объекты могут быть действительными и живыми, но не связь (self.delegate) между ними.Проверьте это, пожалуйста.В doStuff, в ветке «Done», покажите адрес self.delegate с

NSLog(@"%p", self.delegate);

перед вызовом done: и сравните его с адресом основного контроллера.

0 голосов
/ 31 августа 2011

Попробуйте выполнить проверку протокола и метода перед вызовом, как в коде:

- (void) doStuff 
{
    if(mode == Done) 
    {
        NSLog(@"Done. Handling back control");//this is the last log displayed by the console
        if ([delegate conformsToProtocol: @protocol(ParentControllerDelegate)])
        {
            if ([delegate respondsToSelector: @selector(done:)] == YES)
            {
                [delegate performSelector: @selector(done:) withObject: self];            
            }
        }
    } 
    else 
    {
       // some controller code
0 голосов
/ 31 августа 2011

Просто дикая догадка, но если это "время от времени", это вероятно viewDidLoad или viewDidUnload, вызывающее EXC_BAD_ACCESS после получения предупреждения о памяти. Проверьте ваши освобожденные / сохраненные / созданные переменные экземпляра в вашем родительском / дочернем контроллере, особенно в вышеупомянутых методах загрузки представления.

...