Objective-C / Cocoa creation release order? - objective-c

I am just curious if the order expressed for the release of objects should reflect the reverse of their order in the hierarchy:
// Psuedo code
alloc OBJ_001;
alloc OBJ_001 > OBJ_002;
alloc OBJ_001 > OBJ_002 > NSSting;
release NSString;
release OBJ_002;
release OBJ_001;
I am pretty sure it should (makes sense to me), but have not seen any mention of this in my learning so far.
Gary

It doesn't matter. I assume you mean that OBJ_001 owns OBJ_002 owns the NSString instance, and you own all three objects (co-owning the NSString with OBJ_002 and co-owning OBJ_002 with OBJ_001).
Doing it in reverse order:
Release NSString instance: Nothing happens, because OBJ_002 still owns it.
Release OBJ_002: Nothing happens, because OBJ_001 still owns it.
Release OBJ_001: It releases OBJ_002, which releases the NSString. All three dealloc.
Doing it in the same order:
Release OBJ_001: It releases OBJ_002, then deallocks. OBJ_002 still exists because you still own it.
Release OBJ_002: It releases the NSString, then deallocks. The NSString still exists because you still own it.
Release NSString instance: It deallocks.
Either way, all three instances dealloc. There is no difference.
I prefer the reverse order, but that's purely a style choice.

I wouldn't say so, as long as you're done using it you can release it whenever you want.

Related

Leaking objects, and I need to fix it

I'm importing some older ObjC code, circa 2006, to the latest Xcode. It was written before the era of ARC, and I don't have a strong handle on the previous system. Looking for some advice on how to diagnose these.
Here's an example, one of hundreds...
sym = [ globals addObject:[ [ NCObject alloc ] initWithArray:saved dimension:dimension type:type ] ] ;
The error isn't specific, do I need an autorelease around the entire thing, or one immediately after "type ]"?
I seem to recall that the basic rule is that if I see an inti, I need to autorelease it. Are there other cases I need to think about?
Yes. Autorelease is right. The alloc creates an rc=+1 object. Adding it to the array makes it +2. Autorelease will leave it at +1, which is where you want it. Releasing the globals array eventually will bring it back to 0, which is also desired behavior.
For clarity:
sym = [[NCObject alloc] initWithArray:saved dimension:dimension type:type];
[globals addObject:sym];
[sym autorelease];
Note that release is just as good in this case (a little better because it doesn't leave any autorelease pool work for later). Unless the function returns sym, you can release.
alloc... (any method that starts with alloc), new, copy..., mutableCopy... give you retained objects (thanks to #jlehr for extending the original list).
Collections retain
objects that are contained in them (in your case, globals retains
that NCObject that you create.
You should balance every retain
that you write with a release or autorelease. If you release an object, you can't use it anymore, because if its
retainCount has reached zero, it will be deallocated instantly. An
autoreleased object will live until the nearest autoreleasepool
drain.
In the example that you wrote, you either have to balance an alloc, so you have to either release your NCObject after you've added it to the array (if you release it before that, it will most likely be deallocated), or autorelease it whenever you want.
But I would really recommend you to read Apple's Advanced Memory Management Programming Guide. It's short. And it describes all the rules that you'll need.

NSString assignment, release required?

If I have a property in my class like so:\
#interface Test
NSString *str;
#end
And in my init in the .m:
str = #"Test";
Do I need to manually release that in the classes dealloc?
What about this kind?
NSString *myStr = [NSString stringWithFormat:#"%#", someString];
Do I need to release that too?
You should really just use ARC, but to answer your specific question, no: you don't need to release those. You only release what you "own", and you only own things you got from a method that contains one of [new, alloc, retain, copy].
That said, since you don't own those strings, you should retain (or copy) them if you need them to stick around.
You shouldn't have to release if you are using ARC in your project (Automatic Reference Counting). ARC is enabled for iOS 5+ so if you are targeting iOS 5 or higher, you dont have to release anything.
If you're not sure if you're using ARC or not, just try to release/retain. If it shows a warning saying you can't release/retain, ARC is enabled, else is disabled and you'll have to retain & release.
Both constructs1 create autoreleased strings. You need to retain them (explicitly or by assigning to a retained property), otherwise you will end up with dangling references once the autorelease is called2. Once you call a retain on an object, releasing it becomes your responsibility.
A more robust approach with NSStrings is to use copy properties, rather than retaining them. Doing so lets you avoid issues when a NSMutableString passed into your init method gets mutated after you have validated its content.
1 I am assuming that you are asking about pre-ARC version of Objective C tools; otherwise, you will not be able to call retain or release explicitly.
2 This usually happens some time after you exit from the method, and the control passes back to the run loop.

Is AutoRelease redundant when using ARC in Objective-C?

I'm pretty new to Objective-C, as you may gather, and until recently, I hadn't really understood the need for all this AutoRelease malarky. I think that's mostly because I've started Objective-C with ARC, and haven't had any exposure to doing retains and release.
Anyway, my understanding now is that pre-ARC, if you created an object and needed to return a pointer to it as the returning object of the method/function, you would need to autorelease it, because you are unable to do the "[obj release]" after doing "return obj;"
Worrying about retains and releases isn't an issue with ARC. Does this mean that in our own code, there is really point in creating our own autoreleased objects? Ie, doing [[[Class alloc] init] autorelease]? From what I've gathered, we should still setup autorelease pools, but only because other frameworks or libraries may still return autoreleased objects, but we no longer need to explicitly create autoreleased objects ourselves - is this a fair understanding?
Thanks,
Nick
When using ARC, you do not want to do any memory management yourself. Specifically you will not be calling release and auto release because it does it all for you. In fact, the compiler should probably complain if you try to manage memory yourself.
Instead of [[[Class alloc] init] autorelease]; you'll just call [[Class alloc] init];
I recommend reading this blog post for some really good background on ARC and memory management in general.
Well, your understanding is quite correct. With ARC we do not release or autorelease any more. Just have to make sure that we assign nil (or some other reasonable value) to any reference to objects, which we do not need any more. In the worst case we could still constantly consume additional memory but the memory cannot leak any ore.
And yes, we still maintain autorelease pools for the sake of using framework libraries (linked ones) that may not use ARC.
To answer your question between the lines about the purpose of autorelease. This applies to non-ARC project only, of course.
In the good old days Objective-C did not offer any reference counting but its retain counting. Any allocated memory of objects, that are not retained (or have a retain count of 0) is considered free and may soon be claimed and used by other objects.
This means that every object needs to be retained after its allocation, assuming that you want to keep it around. When the object is not used any more then you need to release it. This comes with two risks. Well, alloc does retain it once automatically.
1) You may forget to release an object that is unused. In the worst case you may even loose all references to an object that stays in memory for ever since.
2) You may still refer to an object hat has been released already and then try accessing it which will most likely end in an BAD_EXC exception.
All this can be quite annoying. In order to get rid of some of these obligations for objects that don't stay around very long, the autorelease was invented. For temporary objects only you alloc it (release-count = 1) and autorelease it. That means that the object will be automatically released (retain count reduced by 1) within the next autorelease circle. But the object remains allocated for your method while it is being executed. Typically the reference variable would be a local one.
Sample:
-(void) myMethod{
AClass *someObject = [[[AClass alloc] init] autorelease];
// use the object
// probably hand it to another object if that takes ownership, i.e. add it ot an Array using addObject:
// don't care any more
}
And that not required any more when using ARC.

Does the NSString returned from NSArray objectAtIndex as autorelease or retain

I have a string returned back from an array, just wonder if I need to release it after using it.
Have a look at this blog post, which does a great job summarizing the rules for Objective C memory management: http://interfacelab.com/objective-c-memory-management-for-lazy-people/.
In particular, rule #1 applies here - you only need to release an object if you own it and you own it if you alloc, copy or new it (or if you explicitly retained it). You didn't do any of those things, so you don't need to release it.
Whether it's autoreleased or not depends on how the string was originally created but you don't need to worry about that since you are not responsible for releasing it.
The objects returned from -objectAtIndex: are technically both.
The code looks something like this:
-(id) objectAtIndex:(NSUInteger) index
{
return [[objects_[index] retain] autorelease];
}
So they don't belong to you, but if you remove it from the array, it won't be immediately deallocated.
autoreleased.
That is with (almost?) any object returned by a method, it would make memory management overly complicated if it wasn't. It is why we all love autorelease.

Reference on when to release in Objective-C

I'm having a recurring problem in Objective-C. I'm either releasing things too many time, or not enough. or perhaps I'm not retaining them enough...
Can someone point me at a good reference that will give me a rule of thumb on when I need to retain and release?
For example:
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
if I alloc an object and only need it in that method, do I need to release it? retain it?
Obviously, if I retained something, I needtorelease it, but beyond that, I get a bit lost.
The rules are generally pretty simple. If you get an object in one of the following ways:
id obj = [[MyObject alloc] init];
id obj = [myObject retain];
id obj = [myObject copy];
id obj = [myObject mutableCopy];
then you need to release it at some point -- in the same method, or your dealloc method, generally. In other words, balance your calls to alloc, retain, copy, and mutableCopy with a matching release call.
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
This happens rarely. The documentation for the called method should specify that you are responsible for releasing the returned object; otherwise, you should assume you're receiving an autoreleased object.
if I alloc an object and only need it in that method, do I need to release it? retain it?
Yes, you need to release it (but you don't need to retain it). (You can also use one of the convenience methods that return an autoreleased object if you're only going to use it in that method.)
There is one and only one canonical reference: Apple's Memory Management Guide for Cocoa or iPhone.