2009-07-30 14 views
5

hay un error muy extraño con mi código ... De hecho, no hay ningún error, solo el depurador comienza con el mensaje "Programar señal recibida:" EXC_BAD_ACCESS "". ¿Alguien puede ayudarme? Estoy absolutamente confundido ... Gracias.iPhone SDK: EXC_BAD_ACCESS con CFRelease para 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; 
} 

salida de la consola es:

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) 

Al pulsar Continuar mensaje salidas "EXC_BAD_ACCESS". Xcode muestra que la última cadena ejecutada en mi código fue CFRelease(addressBookRef);

Respuesta

15

Tuve el mismo problema al hacer algo similar y tras nuevas investigaciones descubrí que estaba a punto de liberar. De acuerdo con la Core Foundation docs:

Si crea o copiar un objeto de infraestructura Core , debe posteriormente liberarlo cuando estás terminado con ella.

Lo leí en el sentido de que las funciones con la palabra Get no deberían ser divulgadas por usted. Si lo hace, causará un problema más adelante cuando el propietario real intente liberarlo. Por lo tanto, en este caso, cuando lo hace:

ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i); 

y posterior:

CFRelease(recordRef); 

están liberando algo que no se supone que debe ser puesto en libertad. Mucho más tarde cuando lo hace:

CFRelease(allPeopleRef); 

la matriz intentará liberar a todos sus registros sin saber que ya ha publicado algunos de ellos. El resultado es tu error Al comentar esa línea puede haber hecho desaparecer el error, pero me temo que ha creado una pérdida de memoria.

le sugiero que no llama CFRelease en Obtener punteros método y hacer llamar en Crear o Copiar método punteros (puede haber excepciones a esta regla, pero hasta ahora funciona para mí).

+0

Muchas gracias. Ahora no hay filtraciones – beefon

+0

brillante, gracias – Eugene

+0

gracias hombre. estupendo –

-2

allPeopleRef y addressBookRef apuntan a los mismos objetos? La copia es probablemente superficial. ¿Qué hace ABAddressBookCopyArrayOfAllPeople?

+0

ABAddressBookCopyArrayOfAllPeople Devuelve todos los registros de las personas en una libreta de direcciones. CFArrayRef ABAddressBookCopyArrayOfAllPeople ( ABAddressBookRef addressBook ); Parámetros addressBook La libreta de direcciones cuya persona registra para volver. Valor devuelto Matriz que contiene los registros de persona en la libreta de direcciones. Disponibilidad Disponible en iPhone OS 2.0 y posterior. declarado en ABPerson.h – beefon

+0

¿Qué ocurre si se comenta CFRelease (allPeopleRef); ? – Sam

+0

¡Gracias por la respuesta! Después de comentar CFRelease (allPeopleRef); ¡funciona correctamente ahora! Gracias.¿Por qué addressBookRef y allPeopleRef apuntan a los mismos objetos? Pensé que la función ABAddressBookCopyArrayOfAllPeople devolverá al menos una copia de todos los registros. – beefon