Неожиданный EXC_BAD_ACCESS в Objective-C - PullRequest
1 голос
/ 06 августа 2009

У меня есть следующий метод:

-(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» в конце, я получу ошибку EXC_BAD_ACCESS в строке (B)! Согласно отладчику, ошибка возникает в CFRetain во встроенном конструкторе + [NSArray arrayWithObjects].

Кроме того, если я закомментирую строку (A) и закомментирую цикл for (...), код выполняется через метод.

Это очень неожиданно для меня. Что я делаю не так в строке (B)? И почему создание совершенно другого массива в строке (A) позволяет методу проходить? И почему комментирование цикла for (...) предотвращает ошибку в строке (B) перед ней?

Может кто-нибудь объяснить, почему это так? Или, по крайней мере, дать мне несколько советов по отладке? Я уже проверил, что метод работает только один раз, и что «self» допустимо.

Ответы [ 2 ]

3 голосов
/ 06 августа 2009

При использовании вспомогательного метода arrayWithObjects необходимо указать nil в качестве последнего элемента.

Документация гласит:

arrayWithObjects:

Создает и возвращает массив, содержащий объекты в списке аргументов.

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

Параметры

firstObj, ...
Разделенный запятыми список объектов, заканчивающихся на nil.

1 голос
/ 06 августа 2009

Добавьте -Wformat к другим предупреждающим флажкам, и компилятор подберет недостающий ноль для вас.

Второй работает после первого, потому что все элементы находятся в одной и той же позиции в стеке. Таким образом, после возврата из первого, стек все еще содержит указатель на [NSNumber numberWithInt:1], указатель на [NSNumber numberWithFloat:2] и nil (и эти указатели даже остаются в силе, так как пул автоматического выпуска еще не был очищен!). Когда вы вызываете второй, без ноля, он заменяет указатели в стеке, но ноль остается неизменным. Если бы ваша вторая попытка имела три числа, она, вероятно, потерпела бы крах таким же образом, поскольку третья цифра перезаписала бы ноль, и тогда оставалось бы то, что было следующим.

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