Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading email address from contacts fails with weird memory issue

I'm stumped.

I'm trying to get a list of all the email address a person has. I'm using the ABPeoplePickerNavigationController to select the person, which all seems fine. I'm setting my

ABRecordRef personDealingWith;

from the person argument to

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {

and everything seems fine up till this point. The first time the following code executes, all is well. When subsequently run, I can get issues. First, the code:

// following line seems to make the difference (issue 1)
// NSLog(@"%d", ABMultiValueGetCount(ABRecordCopyValue(personDealingWith, kABPersonEmailProperty)));

// construct array of emails
ABMultiValueRef multi = ABRecordCopyValue(personDealingWith, kABPersonEmailProperty);
CFIndex emailCount = ABMultiValueGetCount(multi);

if (emailCount > 0) {
    // collect all emails in array
    for (CFIndex i = 0; i < emailCount; i++) {
        CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i);
        [emailArray addObject:(NSString *)emailRef];
        CFRelease(emailRef);
    }
}

// following line also matters (issue 2)
CFRelease(multi);

If compiled as written, the are no errors or static analysis problems. This crashes with a

*** -[Not A Type retain]: message sent to deallocated instance 0x4e9dc60

error.

But wait, there's more! I can fix it in either of two ways.

Firstly, I can uncomment the NSLog at the top of the function. I get a leak from the NSLog's ABRecordCopyValue every time through, but the code seems to run fine.

Also, I can comment out the

CFRelease(multi);

at the end, which does exactly the same thing. Static compilation errors, but running code.

So without a leak, this function crashes. To prevent a crash, I need to haemorrhage memory. Neither is a great solution.

Can anyone point out what's going on?

like image 509
DefenestrationDay Avatar asked Apr 10 '10 10:04

DefenestrationDay


People also ask

Why is my Outlook not remembering email addresses?

Click File, and then click Options. Select the Mail tab. Scroll approximately halfway down until you see Send messages. Make sure that the Use Auto-Complete List to suggest names when typing in the To, Cc, and Bcc lines box is checked.

Why does my email keep saying error?

This is typically due to a mistyped password, but it can also be caused by an incorrect username, connecting to the wrong server, or blacklisting.


1 Answers

It turned out that I wasn't storing the ABRecordRef personDealingWith var correctly. I'm still not sure how to do that properly, but instead of having the functionality in another routine (performed later), I'm now doing the grunt-work in the delegate method, and using the derived results at my leisure. The new (working) routine:

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    // as soon as they select someone, return
    personDealingWithFullName = (NSString *)ABRecordCopyCompositeName(person);
    personDealingWithFirstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    // construct array of emails
    [personDealingWithEmails removeAllObjects];
    ABMutableMultiValueRef multi = ABRecordCopyValue(person, kABPersonEmailProperty);
    if (ABMultiValueGetCount(multi) > 0) {
        // collect all emails in array
        for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
            CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i);
            [personDealingWithEmails addObject:(NSString *)emailRef];
            CFRelease(emailRef);
        }
    }
    CFRelease(multi);
    return NO;
}
like image 148
DefenestrationDay Avatar answered Oct 08 '22 14:10

DefenestrationDay