Should I release this? Memory Management in Objective-C - iphone

Should I release strPhone? What about the coreFoundation object being cast to an NSString? What happens to it?
strPhone = [[NSString alloc] initWithUTF8String: [[(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier] UTF8String]];
Thanks for helping me understand.

You should release or autorelease both. For the NSString, any time you use alloc + init to create an object you are settings its reference count to 1. You are responsible for releasing it when done or autoreleasing it now to allow it to be released at the end of the run loop.
For the CFObject, ABMultiValueCopyArrayOfAllValues returns a CFArray which is “toll-free bridged” to NSArray (meaning it can be used interchangeably with NSArray). Anytime a copy is done - as is implied by the method's name, you are responsible for releasing the returned object. Again, you can release it immediately after you are done with it or autorelease it now to have it be released when the run loop completes.

Yes, both. See Apple's memory management guide for a complete but still pretty brief rundown of memory management in Cocoa.

Remember to NARC on your memory management.
New, Allocate, Retain, Copy. Those are the methods that create objects that YOU'RE responsible for releasing. Aside from those four methods, any new object you get is autoreleased and you don't have to explicitly handle its deallocation.

Related

How to create an autorelease NSDictionary in this case?

I have a NSMutableArray instance called entries and I would like to send one of its value (which is a NSDictionary) to a method, but I'm thinking of how to avoid it to leak or properly release it. Here's what I'm doing right now:
NSDictionary *pdata = [self.entries objectAtIndex:indexPath.row];
[self start_download:pdata];
[pdata release]; // <--> Is it ok to do this ?
Thx for helping,
Stephane
you did not alloc, copy or retain pdata so you don't release it
You should absolutely not release pdata, since you never retained it. -objectAtIndex: returns a non-owned object. If -start_download: needs to refer to pdata after it returns (e.g. if it holds onto it for some asynchronous process) then it should retain pdata itself, and subsequently it should release pdata when it's done, but that's orthogonal to the bit of code you pasted.
If you haven't already done so, you should read the Cocoa Memory Management Rules.
Do you have a delegate method for start_download to handle with the download finished? You should release it then.
I would have start_download do a retain on pdata and then release it when it's done. It's always a good idea to have routines that need to hang on to data to a retain and release themselves, that way you don't care how the object got to you and what's going to happen to it after.

iPhone: using retain vs autorelease

Which one of these is better practice?
A) retain and release the object myself later
NSMutableArray* array = [[self getArray] retain];
....
[array release];
B) autorelease from the function returning the object
getArray {
NSMutableArray* returnedArray = [[[NSMutableArray alloc] init] autorelease];
.....
return returnedArray;
}
The simplest rule of thumb when it comes to memory management in Objective-C is that you should release anything that you've explicitly allocated (alloc), copied (copy), newed up (new), or retained (retain).
The release should be done within the scope of the aforementioned actions. If you allocate space for an object that is returned by a method, you should autorelease it before returning it. So, given the two options you've provided, B is the recommended practice.
You could read and follow Apples guidelines on memory management and performance.
Personally I think the reasons for choosing one way over the other:
Using Autorelease pros:
You can't stuff it up, memory will be freed at some point. That I like to think of as "falling into the pit of success".
cons:
Using autorelease a lot may cause you memory problems as lots of objects build up awaiting be released by the autorelease pools.
Using retain/release pros:
More control when your memory is used/freed.
On ios apple recommends that you use release instead of autorelease whenever possible to keep the size of the pool small.
cons:
Like C/C++ malloc/free new/delete you have to be careful to keep them matched up and it is easy to stuff that up, causing memory leaks.
For member variables you have no choice, retain/release is it.
I think, whichever style you choose comes down to the situation your code is in and choosing the best style based on there pro's and con's. I don't think there is any one answer to this.
If you want to return an object you have to use the second approach. In all cases where possible you should use the retain-release approach because this uses less memory.
If you new, alloc init, retain, or copy (NARC) an object, you have to release it.
When the name of a method starts with any of those words, it means it's being created for the caller, who has the responsibility to release the object when he is done with it.
Otherwise the method returned is not owned by the caller, and he has to indicate he wants to keep it calling retain on the object.
If you can choose, don't abuse autorelease when memory is a concern.
Some comments:
The first rule logically results in the second. Example: if the outcome of a function (the returned object) survives the execution of the function, all the function can do is autorelease the object.
Unless there is a memory/performance concern, the overhead of automatic memory management is better than the memory leak chances plus the increased developing time.
Try to retain/release symmetrically. Example: if you retained on init, then release on dealloc. Same for viewDidLoad/viewDidUnload.
If you use #property(retain) you have to release in dealloc.
Example:
// created with autoreleased, just call retain if you intend to keep it
NSString *orange = [NSString stringWithString:#"orange"];
// created for the caller, you'll have to release it when you are done
NSObject *apple = [NSString initWithString:#"apple"];

Memory Leaks in Objective-C / Arrays

I'm looking at someone's code and I know the general rule is if you have alloc/init, you need to release that memory. He uses a lot of NSMutableArrays, alloc/inits them, but does not release them. Can I simply send the autorelease message to the array that gets created if I do not see any other release/autorelease message getting sent to that array? I basically don't want to get his code to crash and stop working either :P.
With NSMutableArrays, when you send the message addObject and the object in that array increases its retain account, if that array gets released, but the object never gets sent a release or removeObject from the array, is that also a memory leak? Thanks.
You need to either -release or -autorelease anything you -retain, +alloc, -copy, +allocWithZone: or -copyWithZone:. (And, if you retain something twice you also need to release it twice.)
When an NSMutableArray (or NSArray, NSSet, or NSDictionary and mutable subclasses) object is dealloc'd (retain count reaches zero), it releases anything it contains. When you add an object to an NSMutableArray, the array retains the object (it does not copy it like some people claim).
I highly recommend the Memory Management Programming Guide to both you and the someone you referred to in the question.
I hope this answer helps you and someone. Good luck. :)
Also, enable the Clang Static Analyser in the build settings. This will tell you at compile time when a leak is going to happen (and much, much more). In fact, it's the first thing I always do when I start a new project. The analyzer never lied to me.
NSArray and NSMutableArray release all of their objects when they are destroyed, so if the array is managed properly with retain and release (or autorelease) the objects within will not be leaked. But if there are arrays that are never released, they will leak, along with everything inside them.
Without seeing the code, it's hard to advocate for just adding autoreleases everywhere, but for arrays that are used only in the context of a single function (and not assigned to ivars or static variables), the answer is yes, they should be autoreleased. Or more idiomatically, create them with methods like +arrayWithCapacity, which returns an object that has already been added to the autorelease pool.
It is general practice to release all the objects you initialize. But in your case, releasing the array should release all objects as well.
But it all depends on how you are using your objects !!!

Suggest the best way of initialization of array ( or other objects )

I am a bit confused in the following two ways of initialisations.....
Way 1:
- (void) myMethod{
NSArray *myArray = [[NSArray alloc] initWithObjects:obj1,obj1,nil];
[self setClassArray:myArray];
[myArray release];
}
Way 2:
- (void) myMethod{
NSArray *myArray = [NSArray arrayWithObjects:obj1,obj2,nil];
[self setClassArray:myArray];
}
In way 1, I have used a alloc init method which is a instance method and as I have used an alloc statement I have to release the array myself.
In way 2, I have used a static method to initialze the array and as there is no alloc statement used I dont need to release the memory the system will take care of that.
Way 1, is time consuming and can to lead to memory leaks if not taken care
Way 2, is faster in writing and you dont need to take care of memory leaks
But , still i have seen the way1 used in standard source codes more often than the way2. I have no idea why people do this or if I am wrong at some place.
Answers and comments are oppenly invited. Please suggest the best programming practice.
Your second example uses a convenience constructor, which returns an autoreleased object. The question, then, is whether it's better to use autorelease or alloc/release. mmalc's answer on this StackOverflow thread explains the drawbacks of autoreleasing objects. (Basically, use alloc/release whenever possible.)
Also (this may be stating the obvious), some classes might not have convenience constructors, so when working with these you'd have to use alloc/release.
as i know,
[NSArray arrayWithObjects:obj1,obj2,nil];
returns an autoreleased object, smth like
[[[NSArray alloc] initWithObjects:obj1,obj1,nil] autorelease];
and I prefer not to manage memory with autorelease pool. maybe it's just a prejudice))
When using method 2 (autorelease) the object is released when the operating system feels it has no references.
But when using the manual release, as you typed in your code, you can release directly, or whenever you need to.
I usually prefer the second way, and if I recall correctly, this is also what the Apple docs reccommend (use autorelease where possible).
In Way 1 the memory gets released faster, so if you have a method that gets called in a loop or recursively, using autorelease may accumulate much memory, whereas alloc/retain will keep your memory footprint low.
On the other hand I assume that using autorelease is more efficient, because the autorelease pool can release a big chunk of memory at once, instead of small chunks again and again. Tough I may be wrong here.

Sometimes NSString becomes Invalid?

In my own iPhone Application I have used a number of nsstring variables to store values. But sometimes its value becomes Invalid! Does anybody know what may be the reason? Or tell me about the situation when a nsstring variable becomes Invalid?
NSStrings are also objects. They go by the same memory management rules. If you sin against those rules you will get a pointer to invalid memory and it will look like "invalid" data.
For example:
myString = [NSString stringWithString:#"foo"];
This will create an NSString* that's got autorelease on. When you're assigning it to an ivar that autorelease pool will soon pop putting the retain count back to 0 and dealloc'ing it while you still have a reference to it!
Naughty.
Instead, either retain it or use:
myString = [[NSString alloc] initWithString:#""];
This returns an owning reference. Remember to [myString release]; in dealloc.
This is just one example/case of bad memory management. Read the docs on how to properly manage your object lifecycle. Really.
They are being autoreleased. If you create a string using a convenience method (stringWithString, stringWithFormat) it will be added to the autorelease pool.
To stop it being released automatically, sent it a retain message and a release message when you have finished using it so that the memory is released. You can also set up properties to do this semi automatically when you assign the string to a member variable
There are a lot of articles on iPhone (and Mac) memory management here on SO and on the interwebs. Google for autorelease.
If this is for a device with fairly limited resources such as the iPhone, you should use [[NSString alloc] init*] over the static convenience methods, as you will put less pressure on the autorelease pool and lower your memory usage. The pool is drained every message loop, so the less objects to enumerate the better.
You should also be aware that autorelease objects in a loop will generate a lot of garbage unless you manage a local autorelease pool.
did you copy or retain the NSString ?
I asked the same question. And the following answer was the best of convenience. Just use:
[myString retain];
And then in dealloc method (e.g. viewDidUnload):
[myString release];