iPhone应用程序中的EXC_错误访问-内存管理问题

iPhone应用程序中的EXC_错误访问-内存管理问题,iphone,autorelease,Iphone,Autorelease,作为参考,我已经阅读了: 我认为这会有所帮助:) 这个应用程序是一个教学工具,旨在帮助人们将简单的遗传学可视化。只是一些背景,这样变量名和内容就有意义了。以下是应用程序运行时执行的主要代码: - (void)viewDidAppear:(BOOL)animated { ThingzCore *core = [[ThingzCore alloc] init]; ThingzThing *thing1 = [[ThingzThing alloc] init]; thing1.breed

作为参考,我已经阅读了:

我认为这会有所帮助:)

这个应用程序是一个教学工具,旨在帮助人们将简单的遗传学可视化。只是一些背景,这样变量名和内容就有意义了。以下是应用程序运行时执行的主要代码:

- (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];
}
下面是我以各种方式运行它时发生的情况:

  • 它在没有断点的情况下运行,在第二次sleep()之后但在“第三轮”NSLog之前崩溃,没有控制台消息
  • 在启用断点但未定义断点的情况下运行,它将贯穿整个序列。在第四次sleep()之后,它会因EXC_BAD_访问而崩溃
  • 在启用断点和nszombiesenable的情况下运行,它执行与上面相同的操作-没有进一步的信息,只执行EXC_BAD_访问
  • 在仪器中运行时,未显示任何泄漏
这是被调用四次的例程:

-(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];
}
然后:

return possibilities;
它不会向潜在用户发送释放或自动释放消息;我的理解是,以我现有的方式创建数组是一种隐式的自动释放。我不想分配数组,因为我正在返回它,所以没有机会显式释放它

NSMutableArray中保存的对象属于自定义类。增加如下:

ThingzThing *newThing = [[ThingzThing alloc] init];
newThing.breed = choiceBreed;
newThing.gender = choiceGender;
newThing.color = choiceColor;
newThing.pattern = choicePattern;
newThing.generation = mother.generation + father.generation;
newThing.name = @"";
newThing.isEgg = YES;
[possibilities addObject:newThing];
[newThing release];
// get possibilities
NSArray *possibilities = [[self possibilitiesByMatingFather:father 
                                                withMother:mother 
                                                 mutations:isMutation] retain];
这似乎在大多数情况下都有效。至少,当启用断点时,程序会毫无怨言地运行代码,直到结束,如上所述

这里有没有关于我做错了什么的建议?这显然是某种内存管理问题,但我无法在头脑中对其进行分类

顺便说一句,徒劳无功,我试图弄明白,我确实修改了主程序中的一行,如下所示:

ThingzThing *newThing = [[ThingzThing alloc] init];
newThing.breed = choiceBreed;
newThing.gender = choiceGender;
newThing.color = choiceColor;
newThing.pattern = choicePattern;
newThing.generation = mother.generation + father.generation;
newThing.name = @"";
newThing.isEgg = YES;
[possibilities addObject:newThing];
[newThing release];
// get possibilities
NSArray *possibilities = [[self possibilitiesByMatingFather:father 
                                                withMother:mother 
                                                 mutations:isMutation] retain];

无济于事。同样的结果。因此,问题不在于保留可能性通过匹配父:带母:突变返回的数组。在该回报上强制保留也无济于事

在这种情况下,当应用程序停止时,实际错误通常不在调试器中显示的位置

例如,调试器可能指向方法调用,但问题实际上发生在方法内部——而不是在调用方法时


为了追踪情况,我建议在触发错误的方法调用之前设置一个断点——在您的例子中,这将是mateFather:withMother:call。然后进入那个方法。您很有可能会发现问题发生在该方法内部,甚至发生在从该方法调用的方法内部。

请检查类ThingzThing的字符串属性是否有正确的属性声明

e、 g


需要保留或复制而不是分配…

找到它。埋了八个方法调用后,我将释放发送到一个NSArray,它显然是自动释放的。当初始调用例程(ViewDidDisplay)陷入自动释放模式时,它试图自动释放已释放的对象,并发生爆炸。天哪,XCode有没有办法帮我找到这个问题


在任何情况下,如果有人遇到这种情况,请确保您没有向您自己没有明确分配的对象发送发布消息。如果你没有分配它,很可能是自动还原本身,并且你发送一个释放到保留计数否定,基础框架吐出一个Excel BADIAccess。 我知道这是一个愚蠢的问题,但也有可能导致错误。你能删除所有的
sleep()
行吗;嗯。。。只是因为我看不出你的代码有任何错误才尝试:)它在第四次睡眠后会中断吗?是否可能在保留此方法后引发异常?请在此方法的最后一行添加一些NSLog Foo尝试将[NSMutableArray]替换为[[[NSMutableArray alloc]init]autorelease],看看会发生什么…同时发布可能性ByMatingFather methodRemoved sleep();没有变化。在ViewDidDisplay方法的最后添加了一个NSLog,并获得了日志输出,但仍然获得了EXC_BAD_访问权限。见下面对威廉建议的评论。似乎是。唯一的赋值是两种C类型,BOOL和int。所有NSString都是非原子的,retain.Bleh。调试器显示它在苹果的一些代码中出现呕吐。堆栈显示objc_msgSend,然后???,然后_CFAutoreleasePoolPop,然后[NSAutoreleasePool release]。所以我猜这是某种双重释放的情况。必须接受。接受它,因为它给了我线索让我在那里-实际的答案是(正如我已经张贴),我正在释放一个对象,它本身也是自动的-所以进入调试器我带到了一些可爱的基础二进制,而ExcBad BAccess被一个自动清除池试图耗尽自己。