2010-10-05 6 views
2

Для справки, я уже прочитал:EXC_BAD_ACCESS в iPhone приложение - проблема управления памятью

Что я думал, что помогло бы :).

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

- (void)viewDidAppear:(BOOL)animated { 
ThingzCore *core = [[ThingzCore alloc] init]; 

ThingzThing *thing1 = [[ThingzThing alloc] init]; 
thing1.breed = @"AB"; 
thing1.pattern = @"AC"; 
thing1.color = @"CA"; 
thing1.gender = @"XY"; 
thing1.generation = 1; 
thing1.isEgg = NO; 

ThingzThing *thing2 = [[ThingzThing alloc] init]; 
thing2.breed = @"CD"; 
thing2.pattern = @"BA"; 
thing2.color = @"CB"; 
thing2.gender = @"XX"; 
thing2.generation = 1; 
thing2.isEgg = NO; 

NSLog(@"Breeding GD BR PT CL G"); 

ThingzThing *child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 1: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 2: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 3: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

child = [core mateFather:thing1 withMother:thing2]; 
NSLog(@"Round 4: %@ %@ %@ %@ %d",child.gender,child.breed,child.pattern,child.color,child.generation); 
sleep(10); 

[thing1 release]; 
[thing2 release]; 
[core release]; 
} 

А вот что происходит, когда я запускаю его различными способами:

  • Запуск без точек останова, он выходит из строя, без сообщения консоли, после того, как Второй сон(), но до «Round 3» NSLog.
  • Запуск с включенными точками останова, но ни один не определен, он проходит через всю последовательность. После четвертого сна() он сбой с EXC_BAD_ACCESS.
  • Запуск с включенными точками останова и NSZombiesEnabled, он делает то же самое, что и выше, - никакой дополнительной информации, просто EXC_BAD_ACCESS.
  • Работа в приборах не показана.

Это рутина называют четыре раза:

-(ThingzThing *)mateFather:(ThingzThing *)father 
     withMother:(ThingzThing *)mother { 
// will we be doing a mutation? 
int mutationPercentage = father.generation + mother.generation; 
int mutationNumber = (arc4random() % ((unsigned)100 + 1)); 
BOOL isMutation = NO; 
if (mutationNumber <= mutationPercentage) { 
    isMutation = YES; 
} 

// get possibilities 
NSArray *possibilities = [self possibilitiesByMatingFather:father 
               withMother:mother 
               mutations:isMutation]; 
// randomly select one of the possibilities 
int keeping = (arc4random() % ((unsigned)[possibilities count])); 
return [possibilities objectAtIndex:keeping]; 
} 

Без вставки в ВСЮ коде possibilitiesByMatingFather: withMother: функция мутации возвращается в NSMutableArray. Эта процедура объявляет массив с помощью:

NSMutableArray *possibilities = [NSMutableArray array]; 

Это то:

return possibilities; 

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

Объекты, хранящиеся в возможностях NSMutableArray, имеют собственный класс. Они добавляются следующим образом:

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

Любые предложения о том, что я делаю неправильно, здесь? Это, очевидно, проблемы управления памятью, но я не могу разобраться в этом.

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

// get possibilities 
NSArray *possibilities = [[self possibilitiesByMatingFather:father 
               withMother:mother 
               mutations:isMutation] retain]; 

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

+0

Я знаю, что это глупый вопрос, но можно вызвать ошибки. Вы можете удалить все строки 'sleep()'; ммм ... просто пытаюсь, потому что я не вижу ничего плохого в вашем коде :) – vodkhang

+0

он ломается после 4-го сна? Возможно ли, что исключение возникает после того, как этот метод остался? Пожалуйста, добавьте NSLog-Foo в последнюю строку этого метода. –

+0

попробуйте заменить [NSMutableArray array] на [[[NSMutableArray alloc] init] autorelease], посмотрим, что произойдет ... также опубликуйте возможностиByMatingFather method – Daniel

ответ

1

Часто в этом типе ситуации фактическая ошибка не указана в местоположении, показанном в отладчике, когда приложение останавливается.

Например, отладчик может указывать на вызов метода, но проблема действительно возникает внутри метода, а не при вызове метода.

Чтобы отслеживать все, я бы предложил установить точку останова непосредственно перед вызовом метода, который вызывает ошибку - в вашем случае это будет mateFather: withMother: call. Затем перейдите к этому методу. Существует хороший шанс, что вы обнаружите, что проблема возникает внутри этого метода - или даже внутри метода, вызванного внутри этого метода.

+0

Bleh. Отладчик показывает, что он работает в некоторых из кода Apple. Стек показывает objc_msgSend, затем ??, затем _CFAutoreleasePoolPop, затем [NSAutoreleasePool release]. Поэтому я предполагаю, что это случай, когда-то выпущенный дважды. Надо копать. –

+0

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

0

Проверьте, что у вас есть правильные объявления свойств строковых свойств класса ThingzThing.

например.

@property (nonatomic, retain) NSString* breed; 

должны быть сохранять или копировать НЕ назначать ...

+0

Кажется, будет. Единственными назначаемыми являются два типа C, BOOL и int. Все NSStrings являются неатомичными, сохраняйте. –

0

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

В любом случае, если кто-то столкнется с этим, убедитесь, что вы не отправляете сообщение о выпуске на то, что вы явно не распределили. Если вы не выделили его, вероятность того, что он был автореализован сам, и вы отправляете ему релиз, берет отрицательный результат, а Foundation Framework рвется с помощью EXC_BAD_ACCESS.

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