PDA

View Full Version : ABAddressBookCopyArrayOfAllPeople returns autoreleased NSArray?




ashokmatoria
Nov 2, 2011, 08:09 AM
Does ABAddressBookCopyArrayOfAllPeople returns an autorelease'd object?

I was reviewing a code piece (see below) & I want your feedback over memory leak(s) over this statement. Can you pls explain this statement?

NSMutableArray *peopleArray = [[(NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook) autorelease] mutableCopy];


peopleArray doesn't release have any release/autorelease call after this statement.

Thanks.

I'm pretty sure that peopleArray (a mutableCopy) needs to be released explicitly before the enclosing block ends. Currently it has a memory leak due to the absence of [peopleArray release] statement.

As far as inner array is concerned, I believe its right to release (or autorelease) it since that function ABAddressBookCopyArrayOfAllPeople doesn't return an autorelease'd array.

Pls let me know if anyone disagree or has different view point.



RonC
Nov 2, 2011, 01:15 PM
According to the Advanced Memory Management Programming Guide, you own any object you create, and you create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”.

Question 1: Does peopleArray leak?
Since mutableCopy begins with mutableCopy, you own it. That means you need to either pass off that ownership OR release it.

I'd say your code example creates a leak if there is no subsequent release on that object AND that block exits.

By a subsequent release I mean that the automatic variable peopleArray is later assigned to a property/ivar and that property/ivar is subsequently released, or similarly the containing method could return the value and presuming the containing method begins with alloc, new, copy, or mutableCopy, would imply that the returned value is owned and needs to be released.

Question 2: Is autorelease on result of ABAddressBookCopyArrayOfAllPeople correct?

I'd say yes, using the same argument as above - the Copy in ABAddressBookCopyArrayOfAllPeople implies that it returns a retained object, and hence releasing it is necessary. A quick look at the documentation for ABAddressBookCopyArrayOfAllPeople doesn't say one way or the other, so we are left to infer its ownership semantics from its name.

jiminaus
Nov 2, 2011, 03:00 PM
Question 2: Is autorelease on result of ABAddressBookCopyArrayOfAllPeople correct?

I'd say yes, using the same argument as above - the Copy in ABAddressBookCopyArrayOfAllPeople implies that it returns a retained object, and hence releasing it is necessary. A quick look at the documentation for ABAddressBookCopyArrayOfAllPeople doesn't say one way or the other, so we are left to infer its ownership semantics from its name.

This code snippet (http://developer.apple.com/library/ios/#documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/DirectInteraction.html#//apple_ref/doc/uid/TP40007744-CH6-SW1) confirms that the returned CFArray is not (could not be?) auto-released.

PhoneyDeveloper
Nov 2, 2011, 06:38 PM
The naming conventions for CF functions are analogous to those for the Objective C frameworks, but not identical. Look up Create Rule and Get Rule in the docs.

RonC
Nov 3, 2011, 08:39 AM
This code snippet (http://developer.apple.com/library/ios/#documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/DirectInteraction.html#//apple_ref/doc/uid/TP40007744-CH6-SW1) confirms that the returned CFArray is not (could not be?) auto-released.

I looked at the code snippet you referenced and I don't understand what you mean here. Do you mean that instead of autorelease it should be CFRelease?

EDIT: After looking up Get Rule and Create Rule, I think I now understand that it is exactly what you meant. Perhaps a reference should be maintained and then CFRelease'd. So, instead of the original:
NSMutableArray *peopleArray = [[(NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook) autorelease] mutableCopy];
it should be more like:
CFArrayRef *peopleRef = ABAddressBookCopyArrayOfAllPeople(addressBook) ;
NSMutableArray *peopleArray = [(NSArray *)peopleRef mutableCopy];
CFRelease(peopleRef);
// Do stuff with peopleArray
[peopleArray release]; // could have been autorelease on mutableCopy above

jiminaus
Nov 3, 2011, 05:05 PM
Because, and only because, a CFArray is toll-free bridged (http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html) to an NSArray, you can use autorelease or release on it. But normally, yes, for a Core Foundation type you need to call the CFRelease function (or a more more specialised release function for the type).