Несогласованный сбой из-за «сообщения, отправленного на освобожденный экземпляр» в приложении iPhone - PullRequest
1 голос
/ 03 марта 2010

Изначально мое приложение аварийно завершало работу с BAD_EXEC_ACCESS. Я включил NSZombieEnabled, этот вывод ниже. Авария чрезвычайно противоречива. Если происходит сбой, он всегда происходит в одном из трех мест, но не всегда происходит сбой при прохождении этих строк кода. То есть иногда он падает в одном из этих мест в первых 10 взаимодействиях с пользователем, и иногда я могу удерживать элементы управления (когда он проходит через эти строки кода) более минуты, прежде чем он окончательно падает.

Вывод NSZombieEnabled также является непоследовательным, как отмечено в «Сбой места № 2» - два выхода NSZombieEnabled являются примерами сбоя приложения в одной строке кода, но с разными выводами NSZombieEnabled.

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

Правила управления памятью, которым я следую:

  1. Для каждого init / alloc у меня есть соответствующий релиз (Ни в одной точке моего кода это не было бы так сложно, как создание объекта в методе и последующее его освобождение в том же методе).
  2. Для каждого сохраняемого свойства у меня есть соответствующая версия в dealloc ()

(Я слышал о «установке IBOutlets на ноль» в связи с управлением памятью, но я не нашел адекватного описания того, как это делается, поэтому в моем приложении этого не происходит.)

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

Заранее спасибо! Извините, если я слишком длинный и тщательный (INTP)!

-Roben

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

Место аварии # 1:

if (![[self fetchedResultsController] performFetch:&error])

Пример местоположения сбоя # 1 NSZombieEnabled Вывод:

*** -[Not A Type release]: message sent to deallocated instance 0x3b3f570

Место аварии № 2:

NSMutableArray *tips = [NSMutableArray arrayWithArray: [[[categories objectAtIndex: indexPath.row] valueForKey:@"tips"] allObjects]];

Пример местоположения сбоя # 2 NSZombieEnabled Вывод:

*** -[CFArray retain]: message sent to deallocated instance 0x3e53990
*** -[NSFetchRequest retain]: message sent to deallocated instance 0x3b2f2c0

Место аварии № 3:

NSMutableArray *tips = [NSMutableArray arrayWithArray: [[[justOneCategory objectAtIndex: 0] valueForKey:@"tips"] allObjects]];

Пример Crash Location # 3 NSZombieEnabled Вывод:

*** -[UIViewControllerWrapperView retain]: message sent to deallocated instance 0x3e593a0

Пример Backtrace (соответствует строке № 3):

#0  0x01d6a3a7 in ___forwarding___ ()
#1  0x01d466c2 in __forwarding_prep_0___ ()
#2  0x01cfd988 in CFRetain ()
#3  0x01cfd495 in CFArrayCreate ()
#4  0x01d406c3 in -[__NSPlaceholderArray initWithObjects:count:] ()
#5  0x01d5d34a in +[NSArray arrayWithObjects:count:] ()
#6  0x01d6386e in -[NSSet allObjects] ()
#7  0x00003bbc in -[RootViewController getRandomTip:] (self=0x3b24ea0, _cmd=0x7447, sender=0x3b38330) at /Users/***/Classes/RootViewController.m:36
#8  0x00299405 in -[UIApplication sendAction:to:from:forEvent:] ()
#9  0x002fcb4e in -[UIControl sendAction:to:forEvent:] ()
#10 0x002fed6f in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
#11 0x002fdabb in -[UIControl touchesEnded:withEvent:] ()
#12 0x002b2ddf in -[UIWindow _sendTouchesForEvent:] ()
#13 0x0029c7c8 in -[UIApplication sendEvent:] ()
#14 0x002a3061 in _UIApplicationHandleEvent ()
#15 0x0252ed59 in PurpleEventCallback ()
#16 0x01d41b80 in CFRunLoopRunSpecific ()
#17 0x01d40c48 in CFRunLoopRunInMode ()
#18 0x0252d615 in GSEventRunModal ()
#19 0x0252d6da in GSEventRun ()
#20 0x002a3faf in UIApplicationMain ()
#21 0x00002a60 in main (argc=1, argv=0xbfffef9c) at /Users/***/main.m:14

EDIT: добавление некоторого дополнительного кода и вывода, запрошенного Griffo

Спасибо за ответ, еще раз напишите что-нибудь конкретное, что было бы полезно? А пока вот весь метод, который содержит и Crash Location # 1, и Crash Location # 2.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.section == ALLTIPS_SECTION) {

        self.tipsController.title = @"Tips";

        NSError *error = nil;
        if (![[self fetchedResultsController] performFetch:&error]) {
//          NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
//          abort();
        }
        self.tipsController.tips = [NSArray arrayWithArray: [fetchedResultsController fetchedObjects]];

    } else {        

        self.tipsController.title = [[categories objectAtIndex: indexPath.row] name];

        NSMutableArray *tips = [NSMutableArray arrayWithArray: [[[categories objectAtIndex: indexPath.row] valueForKey:@"tips"] allObjects]];

        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending: YES];
        [tips sortUsingDescriptors: [NSArray arrayWithObject: sortDescriptor]];
        [sortDescriptor release];

        self.tipsController.tips = [NSArray arrayWithArray: tips];
    }
    [self.navigationController pushViewController:self.tipsController animated:YES];
}

Я не запускал malloc_history для конкретного аварийного сбоя, о котором вы спрашивали, но я запустил его на # 3, вот этот вывод, я понятия не имею, как я должен анализировать это, поэтому любой совет будет полезен (во всех учебники по malloc_history, которые я прочитал, показывают вывод, и все они похожи на "там, где это есть", а я на "где? wtf ты смотришь"):

* * 1068

Ответы [ 4 ]

3 голосов
/ 03 марта 2010

Несколько вещей на которые стоит посмотреть:

Во-первых, что касается «установки на ноль», это хорошая практика. Каждый раз, когда вы отпускаете что-то, сразу же установите его на ноль. Это означает, что -dealloc часто выглядит так (или дюжина других стилей с точкой с запятой, двумя строками и т. Д.):

[_foo release], _foo = nil;

Но я сомневаюсь, что это твоя проблема. В отправленной вами истории malloc_history показано, что рассматриваемый объект является NSManagedObject, так что это что-то из Core Data. Убедитесь, что вы прочитали Управление памятью с использованием основных данных документы.

Если у вас 10,6, тогда я настоятельно рекомендую статический анализатор. Нажмите Cmd-Shift-A, и он будет искать очевидные ошибки памяти. Я обнаружил, что это довольно хорошо.

0 голосов
/ 10 ноября 2012

У меня была эта ошибка. Я скопировал и вставил код из другого приложения, которое работало немного по-другому. В моем случае я выпускал переменные в viewDidUnload & viewWillDisappear. Я закомментировал выпуски viewWillDisappear, оставил их в viewDidUnload, и приложение работало без сбоев. Надеюсь, это поможет кому-то еще.

0 голосов
/ 03 марта 2010

Именно здесь происходит сбой, но это не значит, что именно в этом и заключается ошибка. Сбой происходит из-за того, что освобожденному объекту отправляется сообщение, но ошибка, вероятно, заключается в том, что объект был освобожден в первую очередь, когда вы все еще хотите его использовать. У меня есть смутное ощущение, что первоначальный освобожденный объект может быть tipsController или fetchedResultsController, и он также освобождает другие вещи.

0 голосов
/ 03 марта 2010

Возможно, из-за автоматического высвобождения объекта, на который вы позже ссылаетесь, что может объяснить несоответствие

Ошибка выпуска «Не тип» может быть связана с тем, что вы выпускаете что-то, что не определено как «что-то» в коде. Вы выполнили команду «shell malloc history» для освобожденного экземпляра, на который ссылается ошибка «не тип»?

Нужно увидеть больше кода на самом деле ...

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