2009-07-30 124 views
5

我的代碼有非常奇怪的錯誤..實際上,根本沒有錯誤,只是調試器以「程序接收到的信號:」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);

回答

15

我有同樣的問題做類似的事情和進一步的研究,我發現我過了釋放。按照Core Foundation docs

如果創建或複製核心 Foundation對象,必須 隨後釋放它,當你 完成它。

我讀到,作爲含義,功能與單詞獲取不應該被釋放你。如果這樣做,當真正的所有者試圖釋放它時,它會在稍後引起問題。所以,當你做這種情況下:

ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i); 

及更高版本:

CFRelease(recordRef); 

你發佈的東西,是不應該被釋放。很久以後,當你這樣做:

CFRelease(allPeopleRef); 

數組將嘗試釋放其所有記錄,不知道你已經釋放了一些人。結果是你的錯誤。通過評論這一行,你可能會讓錯誤消失,但我擔心你已經造成了內存泄漏。

我建議你不要在CFRelease獲取方法指針,做調用它創建複製方法指針(可能有例外情況,但到目前爲止,它爲我的作品)。

-2

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