我有一个EXC_BAD_ACCESS,我似乎无法找出原因

时间:2012-04-12 17:12:58

标签: iphone objective-c ios ios4

所以这是理解我的问题所需的背景代码。在我的视图控制器类中,我有一个创建一个名为levelStart的数组的方法,然后该数组被发送到我的游戏类,该游戏类使用该数组初始化,然后我有一组使用该数组来“玩游戏”的函数。 这是视图控制器代码:

    NSMutableArray* levelStart = [[NSMutableArray alloc] init];
    NSMutableArray* levelFinish = [[NSMutableArray alloc] init];
    NSString* startString = [[NSString alloc] initWithString:@"9999999999988888888998888888899888888889988888888998888888899888888889911888888991188888899999999999"];
    NSString* finishString = [[NSString alloc] initWithString:@"9999999999988888811998888881199888888889988888888998888888899888888889988888888998888888899999999999"];
    int currentsquare;
    for (int i = 0; i < 100; i++) {
        currentsquare = [startString characterAtIndex:i] - '0';
        if (currentsquare == 1) {
            NSNumber* numb1 = [[NSNumber alloc] initWithInt:1];
            [levelStart addObject:numb1];
        }
        if (currentsquare == 2) {
            NSNumber* numb2 = [[NSNumber alloc] initWithInt:2];
            [levelStart addObject:numb2];
        }
        if (currentsquare == 3) {
            NSNumber* numb3 = [[NSNumber alloc] initWithInt:3];
            [levelStart addObject:numb3];
        }
        if (currentsquare == 4) {
            NSNumber* numb4 = [[NSNumber alloc] initWithInt:4];
            [levelStart addObject:numb4];
        }
        if (currentsquare == 8) {
            NSNumber* numb8 = [[NSNumber alloc] initWithInt:8];
            [levelStart addObject:numb8];
        }
        if (currentsquare == 9) {
            NSNumber* numb9 = [[NSNumber alloc] initWithInt:9];
            [levelStart addObject:numb9];
        }
    }
    for (int i = 0; i < 100; i++) {
        currentsquare = [finishString characterAtIndex:i] - '0';
        if (currentsquare == 1) {
            NSNumber* fnumb1 = [[NSNumber alloc] initWithInt:1];
            [levelFinish addObject:fnumb1];
        }
        if (currentsquare == 2) {
            NSNumber* fnumb2 = [[NSNumber alloc] initWithInt:2];
            [levelFinish addObject:fnumb2];
        }
        if (currentsquare == 3) {
            NSNumber* fnumb3 = [[NSNumber alloc] initWithInt:3];
            [levelFinish addObject:fnumb3];
        }
        if (currentsquare == 4) {
            NSNumber* fnumb4 = [[NSNumber alloc] initWithInt:4];
            [levelFinish addObject:fnumb4];
        }
        if (currentsquare == 8) {
            NSNumber* fnumb8 = [[NSNumber alloc] initWithInt:8];
            [levelFinish addObject:fnumb8];
        }
        if (currentsquare == 9) {
            NSNumber* fnumb9 = [[NSNumber alloc] initWithInt:9];
            [levelFinish addObject:fnumb9];
        }
    }
    [startString release];
    [finishString release];
 //NOTE: I took out the intialization of control and level, both which work fine.
    myGame = [[Game alloc] initLevel:level With:levelStart AndFinish:levelFinish WithRows:10 WithColumns:10 WithControl:control];

在我的Game类中,这是初始化方法:

-(id)initLevel:(int)aLevel With:(NSMutableArray*)starter AndFinish:(NSMutableArray*)finisher WithRows:(int)rows WithColumns:(int)cols WithControl:(Coord)aControlSquare{
self = [super init];
if (self != nil){
    level = aLevel;
    squares = [[NSMutableArray alloc] init];
    squares = starter;
    finish = [[NSMutableArray alloc] init];
    finish = finisher;
}
return self;
}

现在它继续冻结的方法是在游戏中,由UIgesture识别器触发,这里是它冻结的线:

 if ([[self squareForCoord:test] intValue] == 8) {
 ...
 }

其中squareForCord接受测试坐标并返回该坐标处的NSNumber。所以我确保我的所有测试都在内部边界,并且它冻结的点是在我的数组的边界内。我相信我正在正确地初始化所有内容,但显然不是,这肯定不是释放发布内容的问题所以我认为它必须是一个初始化问题,请帮忙。

2 个答案:

答案 0 :(得分:2)

您的代码中存在一些问题,但我没有看到EXC_BAD_ACCESS来源,但我对找到它有一些建议。

在此之前 - 这里有一些你可能想要解决的其他事情

  1. 如果您像这样初始化本地字符串

    NSString* startString = @"9999999999988888888998888888899888888889988888888998888888899888888889911888888991188888899999999999";
    

    无需释放它们。这使您更有可能正确地执行此操作。

  2. 迭代字符时,不要硬编码长度。使用字符串的长度

    for (int i = 0; i < [startString length]; i++) {
    
  3. 所有你喜欢的if块

    if (currentsquare == 1) {
        NSNumber* numb1 = [[NSNumber alloc] initWithInt:1];
        [levelStart addObject:numb1];
    }
    

    可以通过这样做来替换(但是,先读#4)

    NSNumber* numb1 = [[NSNumber alloc] initWithInt:currentsquare];
    [levelStart addObject:numb1];
    

    无需检查每个可能的号码

  4. 上面的代码泄露了,所以真的应该是这个

    NSNumber* numb1 = [NSNumber numberWithInt:currentsquare];
    [levelStart addObject:numb1];
    

    每当你分配时,你可能需要释放,除非你将这个责任传递给其他人。如果您阅读addObject文档,您会看到它调用保留,因此它不对您的发布承担责任。在这种情况下,numberWithInt返回一个自动释放的对象。

  5. 此代码

    squares = [[NSMutableArray alloc] init];
    squares = starter;
    

    立即泄漏第一个阵列。您将方块设置为一个数组对象,然后设置完全不同的数组对象。对第一个的引用丢失了。应删除第一行(与完成类似)。

  6. 如果这是一个新项目,那么我建议您立即将其转换为ARC。这将使处理内存变得更加容易。

    但是,如果由于某种原因你不能,请阅读我写的解释EXC_BAD_ACCESS的博客:

    http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html

    简单地说(阅读之后)这是我建议你做的事情

    1. 运行分析并修复它找到的每个错误。它使用ARC使用的相同算法,并且它指出的每个错误很可能是一个真正的问题(它将指出上面的问题#4和#5)

    2. 打开僵尸。我知道你认为你没有向已发布的对象发送消息,并且上面的代码中没有任何实例,但基于我所看到的,我认为很可能存在。僵尸是保留计数为零的对象。当僵尸被打开时,这些对象不再被释放,而是当你向他们发送消息时他们会抱怨。

    3. 如果您在执行此操作后无法找到问题,请查看博客中的其他建议。

答案 1 :(得分:0)

首先,您是否在第一个类实现中发布了levelStart和levelFinish数组?如果是这样,这是一个明确的问题,因为在实例化第二个类之后你没有保留这些对象。我的建议是使用属性来保存第二类中的数组。像

这样的东西
 @property (nonatomic, retain)  NSMutableArray      *squares;
 @property (nonatomic, retain)  NSMutableArray      *finish;

在您的声明中跟随:

@synthesize squares, finish;

在.m文件中,然后最终在初始化程序中进行如此分配:

   self.squares = starter;
   self.finish = finisher;

现在您在新班级中有一个保留的副本。我也会考虑使用:

   myGame = [[Game alloc] initLevel:level With:[ levelStart autorelease ] AndFinish:[levelFinish autorelease] WithRows:10 WithColumns:10 WithControl:control];

提高可读性。另外,我会考虑使用ARC来避免这些问题。