Cocoa memory management rule - cocoa

The Cocoa "Memory Management Programming Guide" document says:
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
Does this also apply to the convenience methods like [NSNumber numberWithFloat:] or [CAAnimation animation]? Should I release these or not?
Thanks!

That statement is still true for convenience methods, in particular the last sentence
Any other time you receive an object,
you must not release it.
This means that you must not release these objects unless you explicitly send them a retain message beforehand.

Those method names do not begin with alloc or new, nor contain copy, nor are they retain. So, no—you do not own the objects those methods return, so you should not release them.

Related

Safe way to generically allocate memory in Cocoa which will be automatically deallocated

In my Cocoa project I had a bunch of places where I used malloc/free. However several months ago I decided to refactor to leverage ARC and in order to do that I tried to make a replacement for malloc which will return a pointer to something that will be automatically cleaned up.
I used this function (error checking and other logging omitted)
+ (void *) MallocWithAutoCleanup: (size_t) size
{
NSMutableData * mutableData = [[NSMutableData alloc] initWithLength:size];
void * data = [mutableData mutableBytes];
return data;
}
This worked fine for awhile, but recently a random memory overwrite issue came up. I tracked down the cause to this function, what appears to be happening is the NSMutableData instance is being deallocated even though I am keeping a pointer to its mutableBytes.
I guess this is happening because the only direct reference to the object is local and is going away, and the mutableBytes points inside the object so the ARC isn't smart enough to deal with that sort of reference counting.
Is there any way I can refactor this code to retain the mutableData object as long as the mutableBytes pointer is being used (i.e. someone has a reference to it)? I know one option is to just return the NSMutableData itself, but that requires some heavy refactoring and seems very messy.
In the 10.7 SDK, -[NSMutableData mutableBytes] is decorated with the NS_RETURNS_INNER_POINTER attribute. This signals to the compiler that the method returns a pointer whose validity depends on the receiver still existing. What exactly ARC does with this is open to change, but currently it retains and autoreleases the receiver (subject to redundant operations being optimized away).
So, the pointer is valid for the duration of the current autorelease pool's lifetime. This is akin to -[NSString UTF8String] (which is decorated in the same way).
ARC is not capable of keeping the mutable data object alive so long as there's any reference to the byte pointer. ARC is not a garbage collector. It doesn't watch all uses of all pointers. It operates locally. It examines one given function, method, or block and emits retains and releases for the behavior of the code as indicated by naming conventions. (Remember that ARC is interoperable with code which hasn't been compiled with ARC support.)
Since a void* isn't an object pointer and can't be retained or released, ARC can't do anything with it. So, in the code calling your -MallocWithAutoCleanup: method, ARC doesn't see anything it can manage. It doesn't emit any special memory management code. (What could it emit at that point?) While compiling the caller, the compiler likely doesn't know anything about the method implementation or the mutable data object inside it.
Think about it another way: if you were still writing manually reference counting code, what would you do in the caller of your method to keep the pointer valid? For the most part (ignoring __weak references), all ARC does is automatically do what you would do manually. Once you consider that you would have no options in that case, you realize that neither does ARC.
I think you answered your own question. If you want to use NSData to manage generic memory allocations, you need to keep a reference to the NSData objects around until you're done with the memory it owns, at which point you nil out your reference(s) to the NSData object in question. This doesn't seem to provide any advantage compared to just manually freeing the malloced memory. Personally, I'd continue to use malloc()/free() explicitly instead of trying to contort my code in such a way that ARC kind of sort of manages malloced memory.
Either that, or I'd write my code such that it doesn't have to use malloc/free in the first place. I'd say the typical "pure" Cocoa project doesn't have many, if any, explicit malloc() calls, and I'd be a little suspicious of code that did unless there was some good reason for it. Why are you using malloc() in the first place?

Cocoa: Object getting autoreleased when it shouldn't

First, I should say I'm using ARC, so retain is not an option. The object's class is of type NSViewController and has two NSTimers as well as several textfields and buttons. The odd thing is that when the two timers are invalidated, it looks like the object is being released. This is a problem because sometimes I just want to pause or restart them, which means I have to invalidate them, but once I do, the reference is lost, and any message to the object will throw a EXC BAD ACCESS.
I'm not very familiar with memory management or ARC but why is the reference lost depending only on the timers? I mean, just because they're invalidated does not mean I don't need the object anymore.
I've tried declaring the timers as instance variables and properties but nothing changed.
What I really need is for the reference not to be retained, even when both timers are invalidated. What am I doing wrong?
NSTimer retains its target, so if it is the only reference to the object it will be deallocated when the timer is invalidated. You'll have to take ownership of your object, preferably by making it a declared strong property.
Edit: Changed "delegate" to "target";
Yes, you'll have to declare a property and (possibly) an instance variable for it.
The release notes give a good example, there are a couple other good intros around. Make sure that you invalidate the timer if your owner class is ever deallocated, otherwise your view controller will hang around.

Is NSObject's retain method atomic?

Is NSObject's retain method atomic?
For example, when retaining the same object from two different threads, is it promised that the retain count has gone up twice, or is it possible for the retain count to be incremented just once?
Thanks.
NSObject as well as object allocation and retain count functions are thread-safe — see Appendix A: Thread Safety Summary in the Thread Programming Guide.
Edit: I’ve decided to take a look at the open source part of Core Foundation. In CFRuntime.c, __CFDoExternRefOperation() is the function responsible for updating the the retain counters. It tests whether the process has more than one thread and, if there’s more than one thread, it acquires a spin lock before updating the retain count, hence making this operation thread safe.
Interestingly enough, the retain count is not an attribute (or instance variable) of an object in the struct (class) sense. The runtime keeps a separate structure with retain counters. In fact, if I understand it correctly, this structure is an array of hash tables and there’s a spin lock for each hash table. This means that a lock refers to multiple objects that have been placed in the same hash table, i.e., the lock is neither global (for all instances) nor per instance.

Is this a correct summary of Cocoa reference counting?

Here's my understanding of it:
Object are only retained (reference counter is incremented):
when init from NSObject is called.
when retain is called.
Objects are only released (reference counter is decremented):
when release is called.
when an autorelease pool containing the object is drained
And to clarify, autorelease does not retain, but just places the object into the top most pool on the autorelease pool stack.
No.
init does not retain, and there are various methods you didn’t mention which do. There is a simple (and also correct) summary in Memory Management Programming Guide for Cocoa.
(There are two exceptions that I’m aware of: the NSPropertyListSerialization methods which provide a retained error string by reference.)

In Cocoa do I need to remove an Object from receiving KVO notifications when deallocating it?

When I've registered an object foo to receive KVO notifications from another object bar (using addObserver:...), if I then deallocate foo do I need to send a removeObserver:forKeyPath: message to bar in -dealloc?
You need to use -removeObserver:forKeyPath: to remove the observer before -[NSObject dealloc] runs, so yes, doing it in the -dealloc method of your class would work.
Better than that though would be to have a deterministic point where whatever owns the object that's doing the observing could tell it it's done and will (eventually) be deallocated. That way, you can stop observing immediately when the thing doing the observing is no longer needed, regardless of when it's actually deallocated.
This is important to keep in mind because the lifetime of objects in Cocoa isn't as deterministic as some people seem to think it is. The various Mac OS X frameworks themselves will send your objects -retain and -autorelease, extending their lifetime beyond what you might otherwise think it would be.
Furthermore, when you make the transition to Objective-C garbage collection, you'll find that -finalize will run at very different times — and in very different contexts — than -dealloc did. For one thing, finalization takes place on a different thread, so you really can't safely send -removeObserver:forKeyPath: to another object in a -finalize method.
Stick to memory (and other scarce resource) management in -dealloc and -finalize, and use a separate -invalidate method to have an owner tell an object you're done with it at a deterministic point; do things like removing KVO observations there. The intent of your code will be clearer and you will have fewer subtle bugs to take care of.
A bit of extra info that I've gained by painful experience: although NSNotificationCenter uses zeroing weak references when running under garbage collection, KVO does not. Thus, you can get away with not removing an NSNotificationCenter observer when using GC (when using retain/release, you still need to remove your observer), but you must still remove your KVO observers, as Chris describes.
Definitely agree with Chris on the "Stick to memory (and other scarce resource) management in -dealloc and -finalize..." comment. A lot of times I'll see people try to invalidate NSTimer objects in their dealloc functions. The problem is, NSTimer retains it's targets. So, if the target of that NSTimer is self, dealloc will never get called resulting in some potentially nasty memory leaks.
Invalidate in -invalidate and do other memory cleanup in your dealloc and finalize.

Resources