Core Foundation objects and retain/release messages - objective-c

Let's say we have some Core Foundation objects, such as CGColorRef, that are added to an NSArray like this:
CGColorRef color = ...;
NSArray *array = [NSArray arrayWithObject:(id)color];
Since arrays retain their contents, color receives a retain message (not CFRetain(), right?). What happens in this case from memory management point of view?

From Core Foundation Design Concepts:
Note from the example that the memory management functions and methods are also interchangeable—you can use CFRelease with a Cocoa object and release and autorelease with a Core Foundation object.
It doesn't specifically mention retain, but, in practice, that works as well, as do copy (various classes' CFFooCreateCopy) and description (CFCopyDescription). The last is how you can pass CF objects as the value for a %# formatting specification when using NSLog and other string-formatting functions and methods.
The result is the same: retain does the same as CFRetain, release does the same as CFRelease, etc.
A few things to be aware of:
Prior to iOS 7 and OS X 10.9, there is no CF counterpart function to NSObject's autorelease method. (7 and 10.9 brought the CFAutorelease function.) If you're not using ARC, then, as mentioned in the documentation quoted above, you can send autorelease to a CF object, and it works the same as on an NSObject.
You can send a message to nil, but you can't call CF functions on NULL (you'll crash). Quartz has some class-specific functions, such as CGContextRetain/Release, that include a NULL check; whether you want to use those or always do your own NULL checks is a matter of style.
CF's retain and release functions work under garbage collection, whereas retain and release messages are no-ops (as if sent to nil). Doesn't matter unless you're working on a GC'd Mac app, in which case you will need to use CFRetain and CFRelease on CF objects.
Similarly, under ARC, retain and release messages will be illegal and CF objects won't be automatically reference-counted. You will need to use CFRetain and CFRelease on CF objects.
Collections always do the right thing, as documented. Usually, this means a strong reference. Outside of GC, that means the collection (array, dictionary, etc.) will retain and release its objects, whether automatically (by assignments, if its code is ARCified) or manually (by explicit retain and release messages).

Related

Release allocated or initialized object in objective-c?

Memory management says we must release an object created with alloc. Consider this typical example code.
XYZClass *obj = [[XYZClass alloc] init];
// use obj
[obj release];
But in this example, obj may not be the object returned from alloc, as Apple's documentation says
Note: It’s possible for init to return a different object than was created by alloc, so it’s best practice to nest the calls as shown.
So this typical example seems to release the object returned from init, breaking memory management rules, and not release the object returned from alloc, further breaking the rules.
How is this typical example valid?
First of all you code uses manual memory management, that is something I would not recommend, since Xcode 4.2 for OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS we have support for Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. See Transitioning to ARC Release Notes :
Instead of your having to remember when to use retain, release, and
autorelease, ARC evaluates the lifetime requirements of your objects
and automatically inserts appropriate memory management calls for you
at compile time. The compiler also generates appropriate dealloc
methods for you.
With regards to your specific question, the fact that init might return a different object does not break the memory management, because that different object will use the same allocation. This is quite common for class clusters that the initializer might return a internal subclass.

Objc Cocoa MRC - Released and autoreleased objectsI have to write him up to see application

I'm writing a C++ application using Metal API (objective C) and MRC (Manual Reference Counting). I have a very limited experience with ObjC. Most of the Metal API objects are defined as protocols and created as an object returned from C-function or other object's method (ex. MTLDevice newBufferWithLength). To know how to release objects created this way I need to know if they have been set autoreleased or not (I can't call release an autoreleased object with retain count 1 for instance). The problem is I can't find any description in Metal API documentation which would answer this question. I've only read in user guide that all so called lightweight objects are created autoreleased. There are three examples of autoreleased objects but not sure if I can just assume that rest of the objects are not autoreleased. In cocoa many objects also may be created without alloc+init, being returned from a static method (ex NSString string) so the problem seems not to be only Metal related.
Thank you for your help.
The usual Objective-C rule is that creating scope is also responsible to release object. So, in virtually all cases, except well-documented exceptions, returned object is autoreleased (both returned through return value or out-arguments). More correct way to see it is that object is always returned with +0 scope-local retain count, so you are expected to retain it if needed. Reading the manual it seems that Metal API is one of Apple's frameworks, so it should follow this rule unless warned with bold statements. C functions in Objective-C are also expected to behave that way. (There is no difference between a method and a function in terms of resource management.)
For that "alloc-init vs. [NSString string]" part: MRC code either returns [NSString string], which is already +0, or [[[NSString alloc] init] autorelease]. Otherwise it breaks the convention. Exceptions are -[init] and +[new...] methods itself that return +1. Under ARC there is no difference between alloc-init/string, because ARC knows the convention and does the right thing, optimizing excessive retains/releases where possible.
Also note that -[retainCount] is meaningless and "considered harmful", because you never know how many retain-autorelease calls were performed and what objc-runtime accounting is in effect even with your own objects.
ARC is really a great option unless you're writing some sort of Objective-C -to- Whatever bridge, where retain counts and/or cycles must be managed explicitly due to lack of context. It doesn't take anything from you, giving in most cases a big advantage of not managing resources at all.

Dealloc and ARC

I read that when using ARC in Objective-C programming in Xcode the dealloc method is called automatically by the compiler. Under what circumstances is it called?
In order to avoid having too many variable names, when I need to repeatedly use the same classes to do multiple operations (and resetting the variable each time) I often declare the variables, set them to nil, and then assign values to them as I go. This ends up looking like this:
MyClass mc;
mc = [[MyClass alloc] init];
[mc doThis:someOption]
mc = [[MyClass alloc] init];
[mc doThis:someOtherOption];
//etc...
The method name alloc is short for "allocate" because it is the method where memory is allocated to the variable. Does the compiler automatically release the memory for sc every time I assign it a new value? I plan on using this method in a project of mine, and I don't want a lot of memory being allocated with all the times I call alloc to assign a new value to mc.
The compiler never calls dealloc. The compiler inserts retain, release and autorelease (more efficient equivalents, really) as necessary to follow the memory management rules.
When the compiler inserts said calls is up to the compiler and the details will change across different compiler versions and different optimization levels.
I.e. you shouldn't need to worry about it in general.
However, autorelease pressure can still be an issue, as can retain cycles. Thus, you should definitely poke about your app with the Allocations Instrument to both measure the high-water mark and make sure your app isn't leaking memory over time.
I read that when using ARC in Objective-C programming in Xcode the dealloc method is called automatically
In Objective-C, you never call -dealloc directly whether or not you're using ARC.
Under what circumstances is it called?
-dealloc is called when an object's retain count drops to zero. That is, it's called when all the objects that had previously asserted "ownership" of the object (by calling +alloc or -retain or -copy or +new) have renounced that ownership (by calling -release or -autorelease).
Does the compiler automatically release the memory for sc every time I assign it a new value?
If you're using ARC (and you should be), the compiler will insert appropriate calls to -retain, -release, etc. so that memory is managed appropriately. That said, you still need to understand how memory management works, and you should be familiar with the material in Advanced Memory Management Programming Guide.
Under ARC, your variable mc will hold a strong reference to only one instance of MyClass at a time, so when you allocate the second one and assign it to the variable, the first one should be getting deallocated, assuming your doThis: method doesn't do something that will create another strong reference to that instance, or that you're not doing anything else in your code that you've omitted that will keep a strong reference.
That being said, it would be a good idea for you to run your app with Instruments to see how much memory your app uses during this. Your instances shouldn't be getting autoreleased, so you shouldn't have to worry about them remaining around until the autorelease pool is drained, but I don't know what you might being doing when you init an instance of the class, or what you might be doing in your doThis: method, so if you're concerned, it's always a good idea to profile it with Instruments for memory allocations and leaks.

What are the differences between free, dealloc, release, and autorelease?

Can someone explain the differences between free(), release, autorelease and dealloc?
free() is a C function that you use to dispose of no longer needed memory you obtained through malloc() or other function that is documented to require free() to deallocate its memory e.g. strdup().
-dealloc is an Objective-C selector that is sent by the Objective-C runtime to an object when the object is no longer owned by any part of the application.
-release is the selector you send to an object to indicate that you are relinquishing ownership of that object. Once an object is not owned by anybody, it is sent the -dealloc message by the runtime.
-autorelease is a selector you send to an object to indicate you are relinquishing ownership of the object. However if nobody now owns the object the final -dealloc will be deferred until some unspecified later point. In fact, what you are really doing is transferring your ownership to an autorelease pool which will then release it when it is itself released (or drained).
You must never send -dealloc to an object except to super in the object's own -dealloc method.
Out of the 4 methods you've mentioned you'll typically only use release and autorelease in objective-c. free maybe used when you've used c and malloc otherwise you should use release and autorelease.
dealloc shouldn't be called by any of your code as it can interfere with the retain/release cycle that objective-c uses to keep track of resources. Using dealloc will almost certainly result in crashes at runtime if you ever use it.
The ultimate resource of the use of the release and autorelease is the Apple memory management documentation
free is the opposite of malloc and is used in C. You'll likely not use it very much programming in Objective C
If you own an object, you release it when you're done with it
You can also autorelease an object. This automatically releases it at the end of the current run loop iteration
When the reference count on an object drops to zero, the runtime calls dealloc. You should not call this method yourself
You "own" an object if you alloc, new, retain or copy it.
Apple provide some good documentation on this.

Releasing Core Foundation object references

Do I need to release a Core Foundation objects to clear up memory? And if so, how?
For example, in the code:
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
do I need to release peopleArray? What about addressBook?
Yes, in CoreFoundation you have to release anything with Create or Copy in the name. You do this with CFRelease(). In your case, you should be releasing both the array and the address book references.
The rules for memory management in Core Foundation are similar to those in Cocoa: if the method that returns a reference contains the words "create" or "copy", you own the reference and must call CFRelease() on that reference to relinquish ownership. Otherwise, you do not own the reference and must call CFRetain to take ownership (necessarily requiring a subsequent CFRelease to relinquish that new ownership). These rules, as taken from the Memory Management Programming Guide for Core Foundation are:
If you create an object (either
directly or by making a copy of
another object—see “The Create
Rule”), you own it.
If you get an
object from somewhere else, you do
not own it. If you want to prevent it
being disposed of, you must add
yourself as an owner (using
CFRetain).
If you are an owner of an
object, you must relinquish ownership
when you have finished using it
(using CFRelease).
In your example, both the addressBook and the peopleArray must be released. Since there is no autorelease equivalent in Core Foundation, if you are returning the a reference from a method, return the array without releasing it. You should (unless you're being evil) then include "create" in the method name to indicate to the caller that they now own a reference to the returned object. In this case, CFArray is toll-free bridged to NSCFArray, an Objective-C object that inherits from NSObject. You can thus cast peopleArray to an NSArray* and autorelease that, if you need to return it from a function/method:
return [(NSArray*)peopleArray autorelease];
Note that this only works for toll-free bridged classes. My understanding is that it's rather difficult to make your own toll-free bridged classes and only the primitive (string, array, etc.) CF classes are toll-free bridged, so this approach won't work always. Finally, if you can avoid using autorelease (i.e. you can make your memory management more explicit), that's probably always a good thing.
Another small point that no-one has mentioned yet, some CF classes have a "toll-free bridge" with their NS counterpart. CFString and NSString, CFArray and NSArray are both examples. This is relevant as you can just use release with these classes.
See this other StackOverflow question for more information.
I would suggest reading Apple's guide on Core Foundation memory management for an in-depth discussion of this. They have a similar guide for general Cocoa memory management as well.
To release a CF object, you would call the CFRelease function.
For ARC you can use.
return (__bridge_transfer NSArray*)peopleArray;
"__bridge_transfer" will transfer the ownership to ARC and therefore you don't need any further release call.