iPhone SDK:ABAddressBookRefのCFReleaseを使用したEXC_BAD_ACCESS
-
05-07-2019 - |
質問
私のコードには非常に奇妙なエラーがあります。実際、エラーはまったくありません。デバッガは「プログラム受信信号:“ 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)
Continueを押すと&quot; EXC_BAD_ACCESS&quot;が出力されます。メッセージ。 Xcodeは、私のコードで最後に実行された文字列が CFRelease(addressBookRef);
解決
似たようなことをしているときに同じ問題を抱えていたので、さらなる調査の結果、リリースが過剰だったことがわかりました。 Core Foundationのドキュメントによると:
コアを作成またはコピーする場合 財団オブジェクト、あなたはする必要があります その後、それを解放します それで終わりました。
「Get」という単語を含む関数がリリースされるべきではないという意味として読みました。実行すると、後で実際の所有者がリリースしようとすると問題が発生します。したがって、この場合は次のようにします。
ABRecordRef recordRef = CFArrayGetValueAtIndex(allPeopleRef, i);
以降:
CFRelease(recordRef);
リリースされるはずのないものをリリースしています。後でやる:
CFRelease(allPeopleRef);
配列は、あなたがすでにいくつかのレコードをリリースしたことを知らずに、すべてのレコードをリリースしようとします。結果はエラーです。その行をコメントアウトすることで、エラーを解消できたかもしれませんが、メモリリークが発生した可能性があります。
Get メソッドポインターで CFRelease
を呼び出さず、 Create または Copy で呼び出すことをお勧めしますメソッドポインター(このルールには例外があるかもしれませんが、今のところはうまくいきます。)
他のヒント
allPeopleRefとaddressBookRefは同じオブジェクトを指しますか?コピーはおそらく浅いです。 ABAddressBookCopyArrayOfAllPeopleは何をしますか?