2

メモリ管理に関連している可能性が非常に高いクラッシュがありますが、それを見つけることはできません。

クラッシュは発生したことがありません。受け取ったクラッシュ レポートが原因で発生していることだけはわかっています。
これはまた、クラッシュが修正されたことを確認する現在の唯一の方法は、アプリを出荷してクラッシュ レポートが届くのを待つか (悪いニュース)、そうでないか (幸いなことです!) であることも意味します。

クラッシュレポートの抜粋:

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0x9
Crashed Thread:  0

Thread 0 Crashed:
0   CoreFoundation                      0x375f29e8 0x375e4000 + 59880
1   MyApp                            0x000bf22f -[UIViewController(AddressPicker) fullNameAndAddressFromPerson:identifier:] (UIViewController+AddressPicker.m:108)
2   MyApp                            0x000bf3f9 -[UIViewController(AddressPicker) guessedUserAddress] (UIViewController+AddressPicker.m:161)
3   MyApp                            0x0009cc99 -[RecipientsViewController loadUserAddressFromMyAppSender] (RecipientsViewController.m:190)
4   MyApp                            0x0009c189 -[RecipientsViewController viewDidLoad] (RecipientsViewController.m:78)
5   UIKit                               0x31a5e541 0x31a3c000 + 140609

元のコード:

- (NSString *) fullNameAndAddressFromPerson:(ABRecordRef) person identifier:(ABMultiValueIdentifier) identifier {
    NSMutableString *address = [NSMutableString new];

    // Get and add first and last name
    CFStringRef cfFirstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *firstName = (NSString *)CFBridgingRelease(cfFirstName);

    CFStringRef cfLastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSString *lastName = (NSString *)CFBridgingRelease(cfLastName);

    [address appendFormat:@"%@ %@\n", firstName ?: @"", lastName ?: @""];


    // Get and add address
    ABMultiValueRef addressMultiValue = ABRecordCopyValue(person, kABPersonAddressProperty);

    CFTypeRef addressRef = ABMultiValueCopyValueAtIndex(addressMultiValue, ABMultiValueGetIndexForIdentifier(addressMultiValue, identifier)); // This is line 108
    CFRelease(addressMultiValue);

    NSDictionary *addressDictionary = (NSDictionary *) (CFBridgingRelease(addressRef));

    if ([addressDictionary isKindOfClass:NSDictionary.class]) {
        [address appendString:ABCreateStringWithAddressDictionary(addressDictionary, YES)];
    }

    return [address stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

Nirav によって提案されたチェックを含む更新されたコード:

- (NSString *) fullNameAndAddressFromPerson:(ABRecordRef) person identifier:(ABMultiValueIdentifier) identifier {
    NSMutableString *address = [NSMutableString new];
    NSString *firstName, *lastName;

    // Get and add first and last name
    if (person) {
        CFStringRef cfFirstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
        if (cfFirstName) {
            firstName = (NSString *)CFBridgingRelease(cfFirstName);
        }

        CFStringRef cfLastName = ABRecordCopyValue(person, kABPersonLastNameProperty);

        if (cfLastName) {
            lastName = (NSString *)CFBridgingRelease(cfLastName);
        }
    }

    [address appendFormat:@"%@ %@\n", firstName ?: @"", lastName ?: @""];


    // Get and add address
    ABMultiValueRef addressMultiValue = ABRecordCopyValue(person, kABPersonAddressProperty);

    CFTypeRef addressRef;
    if (addressMultiValue && identifier) {
        addressRef = ABMultiValueCopyValueAtIndex(addressMultiValue, ABMultiValueGetIndexForIdentifier(addressMultiValue, identifier));
        CFRelease(addressMultiValue);
    }

    NSDictionary *addressDictionary;

    if (addressRef) {
        addressDictionary = (NSDictionary *) (CFBridgingRelease(addressRef));

        if ([addressDictionary isKindOfClass:NSDictionary.class]) {
            [address appendString:ABCreateStringWithAddressDictionary(addressDictionary, YES)];
        }
    }

    return [address stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

私は明らかなことを見逃していると思うので、「まあ、あなたは正しい」と答える代わりに、バグを修正する可能性が高い回答を受け入れ、このコードをより安全にして改善する方法指摘します。

4

1 に答える 1

1

同様のことをしている同様のクラッシュに直面しましたが、これが私がしたことです:

  • それらを使用する前に、すべての CFStringRef に対して null チェックを実行します - ここでは: cfFirstName、cfLastName
  • ABMultiValueRef が返されるたびに null チェックを行います - ここでは addressMultiValue

等々。要点は、マクロをブリッジする前に null チェックを実行することです。

これは、特定のフィールドが入力されていない電話帳レコードを処理するためのものです。

于 2013-02-01T22:01:50.167 に答える