SDK для iPhone: EXC_BAD_ACCESS с CFRelease для ABAddressBookRef - PullRequest
5 голосов
/ 31 июля 2009

есть очень странная ошибка с моим кодом. На самом деле, ошибок вообще нет, просто отладчик запускается с сообщением «Программа получила сигнал: EXC_BAD_ACCESS». Может кто-нибудь мне помочь? Я совершенно сбит с толку ... Спасибо.

-(NSString *)fullNameForPhone:(NSString *)ph withAlternativeText:(NSString *)text
{
    ABAddressBookRef addressBookRef = ABAddressBookCreate(); 
    NSLog(@"create addressBookRef");
    NSString *stringToReturn = text;

    CFArrayRef allPeopleRef = ABAddressBookCopyArrayOfAllPeople(addressBookRef);  
    NSLog(@"create allPeopleRef");
    CFIndex nPeople = ABAddressBookGetPersonCount(addressBookRef);  

    int i = 0;
    BOOL nameFound = NO;

    while ((i < nPeople) && (!nameFound))
    {
        ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i);
        NSLog(@"   create recordRef");
        CFStringRef allRecordPhonesRef = ABRecordCopyValue(recordRef, kABPersonPhoneProperty);
        NSLog(@"   create allRecordPhonesRef");
        CFIndex nPhones = ABMultiValueGetCount(allRecordPhonesRef);
        int currentPhone = 0;
        for (currentPhone = 0; currentPhone < nPhones; currentPhone++) 
        {
            CFStringRef currentPhoneNumberRef = ABMultiValueCopyValueAtIndex(allRecordPhonesRef, currentPhone);
            NSLog(@"         create currentPhoneNumberRef");
            NSString *currentCleanPhoneNumber = [self cleanPhoneNumberForString:[NSString stringWithFormat:@"%@", currentPhoneNumberRef]];
            if (currentPhoneNumberRef!=NULL)
            {
                NSLog(@"         release currentPhoneNumberRef");
                CFRelease(currentPhoneNumberRef);
            }

            if ([ph isEqualToString:currentCleanPhoneNumber])
            {
                CFStringRef firstName = ABRecordCopyValue(recordRef, kABPersonFirstNameProperty);
                CFStringRef lastName = ABRecordCopyValue(recordRef, kABPersonLastNameProperty);
                NSString *fullName = [self fullNameForFirstName:[NSString stringWithFormat:@"%@", firstName] 
                                                    andLastName:[NSString stringWithFormat:@"%@", lastName]];
                if (firstName != NULL)
                    CFRelease(firstName);
                if (lastName != NULL)
                    CFRelease(lastName);
                stringToReturn = fullName;
                nameFound = YES;
                break;
            }

        }

        CFRelease(allRecordPhonesRef);
        NSLog(@"   release allRecordPhonesRef");
        CFRelease(recordRef);
        NSLog(@"   release recordRef");
        i++;
    }
    CFRelease(allPeopleRef);
    NSLog(@"release allPeopleRef");
    CFRelease(addressBookRef);
    NSLog(@"release addressBookRef");
    return stringToReturn;
}

Вывод на консоль:

2009-07-31 00:20:05.230 abmodular[21747:20b] create addressBookRef
2009-07-31 00:20:05.231 abmodular[21747:20b] create allPeopleRef
2009-07-31 00:20:05.231 abmodular[21747:20b]    create recordRef
2009-07-31 00:20:05.232 abmodular[21747:20b]    create allRecordPhonesRef
2009-07-31 00:20:05.232 abmodular[21747:20b]          create currentPhoneNumberRef
2009-07-31 00:20:05.232 abmodular[21747:20b]          release currentPhoneNumberRef
2009-07-31 00:20:05.232 abmodular[21747:20b]          create currentPhoneNumberRef
2009-07-31 00:20:05.233 abmodular[21747:20b]          release currentPhoneNumberRef
2009-07-31 00:20:05.233 abmodular[21747:20b]    release allRecordPhonesRef
2009-07-31 00:20:05.233 abmodular[21747:20b]    release recordRef
2009-07-31 00:20:05.233 abmodular[21747:20b]    create recordRef
2009-07-31 00:20:05.234 abmodular[21747:20b]    create allRecordPhonesRef
2009-07-31 00:20:05.234 abmodular[21747:20b]          create currentPhoneNumberRef
2009-07-31 00:20:05.234 abmodular[21747:20b]          release currentPhoneNumberRef
2009-07-31 00:20:05.234 abmodular[21747:20b]    release allRecordPhonesRef
2009-07-31 00:20:05.235 abmodular[21747:20b]    release recordRef
2009-07-31 00:20:05.235 abmodular[21747:20b] release allPeopleRef
[Session started at 2009-07-31 00:20:05 +0400.]
GNU gdb 6.3.50-20050815 (Apple version gdb-966)
....
Attaching to process 21747.
kill
quit
The Debugger has exited with status 0.(gdb) 

Нажатие кнопки «Продолжить» выводит сообщение «EXC_BAD_ACCESS». Xcode показывает, что последняя выполненная строка в моем коде была CFRelease(addressBookRef);

Ответы [ 2 ]

15 голосов
/ 26 августа 2009

У меня была та же самая проблема, делающая что-то похожее, и после дальнейших исследований я обнаружил, что я переиздал. Согласно документам Core Foundation :

Если вы создаете или копируете Core Основание объекта, вы должны впоследствии отпустите его, когда вы покончил с этим.

Я понимаю, что это означает, что функции со словом Get не должны быть выпущены вами. Если вы это сделаете, это вызовет проблему позже, когда реальный владелец попытается выпустить его. Итак, в этом случае, когда вы делаете:

ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i);

и позже:

CFRelease(recordRef);

вы выпускаете что-то, что не должно быть выпущено. Намного позже, когда вы сделаете:

CFRelease(allPeopleRef);

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

Я предлагаю вам не вызывать CFRelease на Получить указатели методов и не вызывать его на Создать или Копировать указатели методов (возможны исключения это правило, но пока оно работает для меня).

0 голосов
/ 31 июля 2009

allPeopleRef и addressBookRef указывают на одни и те же объекты? Копия, вероятно, мелкая. Что делает ABAddressBookCopyArrayOfAllPeople?

...