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 ?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With