iPhone SDK:带CFRelease的EXC_BAD_ACCESS用于ABAddressBookRef

问题描述:

我的代码有非常奇怪的错误..实际上,根本没有错误,只是调试器以“程序接收到的信号:”EXC_BAD_ACCESS“”消息开始。 任何人都可以帮助我吗?我非常困惑......谢谢。iPhone SDK:带CFRelease的EXC_BAD_ACCESS用于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; 
} 

控制台输出是:

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);

我有同样的问题做类似的事情和进一步的研究,我发现我过了释放。按照Core Foundation docs

如果创建或复制核心 Foundation对象,必须 随后释放它,当你 完成它。

我读到,作为含义,功能与单词获取不应该被释放你。如果这样做,当真正的所有者试图释放它时,它会在稍后引起问题。所以,当你做这种情况下:

ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i); 

及更高版本:

CFRelease(recordRef); 

你发布的东西,是不应该被释放。很久以后,当你这样做:

CFRelease(allPeopleRef); 

数组将尝试释放其所有记录,不知道你已经释放了一些人。结果是你的错误。通过评论这一行,你可能会让错误消失,但我担心你已经造成了内存泄漏。

我建议你不要在CFRelease获取方法指针,做调用它创建复制方法指针(可能有例外情况,但到目前为止,它为我的作品)。

allPeopleRef和addressBookRef指向相同的对象?副本可能很浅。 ABAddressBookCopyArrayOfAllPeople是做什么的?

+0

ABAddressBookCopyArrayOfAllPeople 返回地址簿中的所有人员记录。 CFArrayRef ABAddressBookCopyArrayOfAllPeople( ABAddressBookRef addressBook ); 参数 地址簿 其人员记录要返回的地址簿。 返回值 包含addressBook中的人员记录的数组。 供货情况 适用于iPhone OS 2.0及更高版本。 声明 ABPerson.h – beefon 2009-07-31 05:19:01

+0

如果您注释掉CFRelease(allPeopleRef),会发生什么情况; ? – Sam 2009-07-31 10:15:15