Objective-C中出现意外的EXC_BAD_ACCESS

时间:2009-08-06 06:02:42

标签: objective-c gcc exc-bad-access

我有以下方法:

-(void)testAPIModule {
    self.requests = [NSMutableArray array];
    NSLog(@"making arrays");
    /*(A)*/ id array1 = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithFloat:2], nil];
    /*(B)*/ id array2 = [NSArray arrayWithObjects:[NSNumber numberWithInt:4], [NSNumber numberWithInt:5]];
    NSLog(@"made array=%@",array2);

    for( ServerRequest *req in self.requests ) {
        [Networker sendRequest:req withDelegate:self];
        [req release];
    }
}

代码按预期运行。

但是,如果我注释掉行(A)或删除它末尾的“,nil”,我会在行(B)处出现EXC_BAD_ACCESS错误!根据调试器,错误发生在+ [NSArray arrayWithObjects]内置构造函数中的CFRetain中。

此外,如果我注释掉行(A)并注释掉for(...)循环,代码将贯穿整个方法。

这对我来说非常意外。我在线(B)做错了什么?为什么在线(A)上创建一个完全不同的数组让方法运行?为什么注释掉for(...)循环会阻止它之前的行(B)上的错误?

有人可以解释为什么会这样吗?或者至少给我一些调试建议?我已经验证该方法只运行一次并且“self”有效。

2 个答案:

答案 0 :(得分:3)

使用方便方法 arrayWithObjects 时,必须将nil指定为最后一个元素。

文档说:

  

<强> arrayWithObjects:

     

创建并返回一个包含参数列表中对象的数组。

+ (id)arrayWithObjects: (id)firstObj, ... 
     

<强>参数

     

firstObj,...
  以逗号分隔的对象列表,以nil。

结尾

答案 1 :(得分:1)

将-Wformat添加到您的其他警告标志中,编译器将为您挑选缺失的零。

第二个在第一个之后工作,因为元素都在堆栈上的相同位置。所以在从第一个返回之后,堆栈仍然包含一个指向[NSNumber numberWithInt:1]的指针,一个指向[NSNumber numberWithFloat:2]和nil的指针(这些指针甚至仍然有效,因为自动释放池还没有耗尽!)。当你调用第二个,没有nil时,它会替换堆栈上的指针,但是nil保持不变。如果你的第二次尝试有三个数字,它可能会以同样的方式崩溃,因为第三个数字会覆盖零,然后下一个将被留下。