2009-07-30 10 views
5

c'è un errore molto strano con il mio codice .. Infatti, non ci sono errori, solo debugger inizia con il messaggio "Program received signal:" EXC_BAD_ACCESS "". Qualcuno può aiutarmi? Sono assolutamente confuso ... Grazie.iPhone SDK: EXC_BAD_ACCESS con CFRelease per ABAddressBookRef

-(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; 
} 

uscita della console è:

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) 

Premendo Continua uscite messaggio "EXC_BAD_ACCESS". Xcode mostra che l'ultima stringa eseguita nel mio codice era CFRelease(addressBookRef);

risposta

15

Ho avuto lo stesso problema facendo qualcosa di simile e dopo ulteriori ricerche ho scoperto che stavo rilasciando. Secondo il Core Foundation docs:

Se si crea o si copia un oggetto Fondazione Nucleo , è necessario successivamente rilasciarlo quando sei finito con esso.

Ho letto che nel senso che funzioni con la parola Get non dovrebbe essere rilasciato da voi. Se lo fai, causerà un problema più tardi quando il vero proprietario tenta di rilasciarlo. Quindi, in questo caso, quando si esegue:

ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i); 

e versioni successive:

CFRelease(recordRef); 

si stanno rilasciando qualcosa che non dovrebbe essere rilasciato. Molto più tardi, quando si fa:

CFRelease(allPeopleRef); 

la matrice tenterà di rilasciare tutti i suoi record non sul fatto che avete già rilasciato alcuni di loro. Il risultato è il tuo errore. Commentando quella linea potresti aver fatto sparire l'errore ma temo di aver creato una perdita di memoria.

suggerisco non si chiama CFRelease su Get metodo puntatori e fanno chiamare sul Creare o Copia metodo puntatori (ci possono essere eccezioni a questa regola, ma finora funziona per me).

+0

Grazie mille. Ora non ci sono perdite. – beefon

+0

geniale, grazie – Eugene

+0

grazie amico. grande –

-2

allPeopleRef e addressBookRef puntano agli stessi oggetti? La copia è probabilmente superficiale. Cosa fa ABAddressBookCopyArrayOfAllPeople?

+0

ABAddressBookCopyArrayOfAllPeople Restituisce tutti i record di persone in una rubrica. CFArrayRef ABAddressBookCopyArrayOfAllPeople ( ABAddressBookRef addressBook ); Parametri addressBook La rubrica di chi registra per restituire. Valore restituito Array contenente i record di persona in addressBook. Disponibilità Disponibile in iPhone OS 2.0 e versioni successive. Dichiarato in ABerson. – beefon

+0

Cosa succede se si commenta CFRelease (allPeopleRef); ? – Sam

+0

Grazie per la risposta! Dopo aver commentato CFRelease (allPeopleRef); funziona correttamente ora! Grazie.Perché addressBookRef e allPeopleRef puntano agli stessi oggetti? Ho pensato che la funzione ABAddressBookCopyArrayOfAllPeople restituirà almeno una copia di tutti i record .. – beefon