Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - Memory leak AddressBook

I was working around AddressBook framework when I've found out some memory leak of different types in my application :

Leaked Object   #   Address Size    Responsible Library Responsible Frame
__NSCFArray 8   < multiple >    256 Bytes   AddressBook ABCMultiValueInsertAndCreateIdentifier
__NSCFString    7   < multiple >    224 Bytes   AppSupport  _sqliteStatementApplyValuesFromRecordWithNullValue
Malloc 32 Bytes 8   < multiple >    256 Bytes   AddressBook ABCMultiValueInsertAndCreateIdentifier
__NSCFArray 8   < multiple >    256 Bytes   AddressBook ABCMultiValueInsertAndCreateIdentifier
ABCMultiValue   8   < multiple >    256 Bytes   AddressBook ABCMultiValueCreate
Malloc 32 Bytes 7   < multiple >    224 Bytes   AddressBook ABCMultiValueInsertAndCreateIdentifier
__NSCFArray 7   < multiple >    224 Bytes   AddressBook ABCMultiValueInsertAndCreateIdentifier
Malloc 32 Bytes 5   < multiple >    160 Bytes   AddressBook ABCMultiValueInsertAndCreateIdentifier

Here's my code :

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {

    SDAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

    ABMultiValueRef multiRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
    NSString *number = (__bridge NSString *) ABMultiValueCopyValueAtIndex(multiRef, 0);
    NSString *firstname = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *lastname = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

    number = (number ? number : @"");
    firstname = (firstname ? firstname : @"");
    lastname = (lastname ? lastname : @"");

    NSDictionary *dic = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:number, firstname, lastname, nil] forKeys:[NSArray arrayWithObjects:kSDPhoneNumberKey, kSDFirstnameKey, kSDLastnameKey, nil]];

    NSMutableArray *numberArray = [NSMutableArray arrayWithArray:appDelegate.contactArray];
    [numberArray addObject:dic];

    [appDelegate setContactArray:numberArray];

    [self.tableView reloadData];

    [self dismissModalViewControllerAnimated:YES];

    return NO;
}

Do someone know which lines are responsible for these leaks ?

like image 200
Yaman Avatar asked Jan 02 '13 11:01

Yaman


People also ask

How detect memory leak IOS app?

Xcode's Memory Graph Debugger If you haven't used this yet, it's easy to access while developing. Tapping on the icon will pause your application and generate a graph of the objects with their references to other objects. If there's leaked memory detected, you will see purple icons on the left pane of Xcode.

What causes memory leaks in IOS?

A memory leak occurs when allocated memory becomes unreachable and the app can't deallocate it. Allowing an allocated-memory pointer to go out of scope without freeing the memory can cause a memory leak. A retain cycle in your app's object graph can also cause a memory leak.

Is memory leak permanent?

Physical or permanent damage does not happen from memory leaks. Memory leaks are strictly a software issue, causing performance to slow down among applications within a given system. It should be noted a program taking up a lot of RAM space is not an indicator that memory is leaking.

How do you pinpoint memory leaks?

To find a memory leak, you've got to look at the system's RAM usage. This can be accomplished in Windows by using the Resource Monitor. In Windows 11/10/8.1: Press Windows+R to open the Run dialog; enter "resmon" and click OK.


1 Answers

In general, any Core Foundation method that has Copy or Create in the name should either transfer ownership to your ARC objects or you must call CFRelease yourself. Thus, you should transfer ownership for your three NSString objects, and manually release multiRef.

To transfer ownership to ARC you should use CFBridgingRelease, which according to WWDC 2012 - Modern Objective-C (about 37:35 into the video), is now preferred over the previous technique, __bridging_transfer (even though, behind the scenes, they're the same thing).

Anyway, the declarations of your three NSString objects should be:

NSString *number = CFBridgingRelease(ABMultiValueCopyValueAtIndex(multiRef, 0));
NSString *firstname = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastname = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));

This is equivalent to:

NSString *number = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(multiRef, 0);
NSString *firstname = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastname = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

Also, don't forget to release multiRef, too:

CFRelease(multiRef);

By the way, if you ran the static analyzer, I believe it would have pointed these out for you. Choose "Analyze" from the "Product" menu, or press shift+command+B.

like image 61
Rob Avatar answered Oct 06 '22 01:10

Rob