Memory Management on the iPhone - iphone

I'm sorry to ask such a simple question, but it's a specific question I've not been able to find an answer for.
I'm not a native objective-c programmer, so I apologise if I use any C# terms!
If I define an object in test.h
#interface test : something {
NSString *_testString;
}
Then initialise it in test.m
-(id)init {
_testString = [[NSString alloc] initWithString:#"hello"];
}
Then I understand that I would release it in dealloc, as every init should have a release
-(void)dealloc {
[_testString release];
}
However, what I need clarification on is what happens if in init, I use one of the shortcut methods for object creation, do I still release it in dealloc? Doesn't this break the "one release for one init" rule? e.g.
-(id)init {
_testString = [NSString stringWithString:#"hello"];
}

There is a neat acronym to remember what you have to release
N.A.R.C - new, alloc, retain, copy.

If it's not created with alloc, new, copy, mutableCopy then you're not responsible for releasing it.
This site has some good quick overviews of things like memory management.
Here's a quote from cocoadevcentral:
If you create an object using the
manual alloc style, you need to
release the object later. You should
not manually release an autoreleased
object because your application will
crash if you do.

Just to clarify things a bit. When you get an object through N.A.R.C. as sylvanaar says you do need to release it. In other cases you are getting an autoreleased object that will be released automatically at some later time. That will be bad in the code you presented here, because you do want this string to stay around at least as long as your object. So you actually need to do an explicit retain to keep it alive for your object.
That is not directly answering your question, but rather anticipating the next one ;-)

If you set an attribute with an autorelease, the object in the attribute can die at anytime beyond the immediate scope. Convenience methods i.e. ones that start with a type: string, array, dictionary etc, return autoreleased objects. You only use autoreleased objects when you don't care whether or not they survive beyond the present scope.
What you really need to do in this case is use accessors, either the synthesized or custom, to manage your retention automatically.
If you do:
#property(nonatomic, retain) NSString *_testString; // .h
#synthesize _testString; //.m
then in code use the reference form:
self._testString = [NSString stringWithString:#"hello"];
... then the only place you have to release _testString is in dealloc. The compiler will create synthesized accessors which will automatically manage the properties memory for you.
By the way, you should not use underscores for names. Apple reserves underscore names for itself so you can get a naming collision.

In the first part of the example you do indeed have to have a release for the string somewhere.
In the second part of the example because its an autoreleased you don't need to call the additional release in the dealloc method. This will actually cause a crash as you are attempting to send a message to something that no longer exists...

On the contrary, you need to retain the object you get from stringWithString:. As you correctly noted, you don't own that object and thus don't need to release it. But because you don't own it, it's free to disappear at any time, leaving you with a crash if you're lucky (and a very odd bug if you're not). So you need to retain the object, and then you do need to release it in dealloc.
All of this is explained very well in the memory management guide. I suggest you read it over a couple of times. It's not very long or difficult, and once you internalize it, you'll never have to wonder again.

The rule is if you create an object with new, alloc, copy or you retain it, you need to release it. Objects created in any other way must not be released.
So in your specific case, you would not need to release your string created with stringWithString.
By the way, I would recommend the Cocoa and Objective-C: Up and Running book for learning more about things like this. Great introduction if you are new to Cocoa programming.

Related

Return Statement Creates and Release an Object

I'm working someone else's code. I've never encountered something like this before:
return [[[NSObject alloc] init] autorelease];
Can someone tell me what this means and why someone would use it? Just to be clear, I'm not asking about the autorelease portion. I would have the same question about this code:
-(id)someMethod
{
lots of lines of code
...
return [[NSObject alloc]init];
}
The autorelease feature indicates that you want to release this object in the FUTURE, but not now because you still need to access it. With the release cycles and releasing of the pool of memory, autorelease is an extremely useful tool in memory management.
You can refer to: http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447 for information on autoreleasing.
Here's a link! What is the difference between releasing and autoreleasing?
Hope this helped!
The object is being allocated, initialized and then added to an autorelease pool.
Quoting Apple documentation (the link above):
Autorelease pools provide a mechanism whereby you can send an object a
“deferred” release message. This is useful in situations where you
want to relinquish ownership of an object, but want to avoid the
possibility of it being deallocated immediately (such as when you
return an object from a method). Typically, you don’t need to create
your own autorelease pools, but there are some situations in which
either you must or it is beneficial to do so.
TL;DR if nobody will retain the object soon, it will be released on the next iteration of the run loop.
It's hard to tell without knowing any details why would anyone want to allocate an NSObject in the first place. I'd suggest searching the project for that method's usage examples and see what happens with the object next.
It is just returning an autoreleased object for convenience. This means that when you use the function you do not have to append autorelease message to it generally speaking. You may always want certain objects to be autoreleased.
As an example, many of the included convenience ("factory") methods in Objective-C return an autoreleased object. You are probably familiar with [NSString stringWithFormat:__FORMAT__] which returns an autoreleased NSString. Take a look at http://memo.tv/archive/memory_management_with_objective_c_cocoa_iphone
As an example of why a function might return an object, consider a synchronous URL request, where you may or may not care about a response, or a function like the following:
- (NSString *)modifyObject:(MyObject *)o {
o.mySettableProp = #"MODIFIED!";
return [o description];
}

When is manual memory management necessary on the iPhone?

Sometimes I see developers use:
ClassA *obj = [[ClassA alloc]...]autorelease];
Why does this sometimes autorelease the objects and sometimes not?
Or is this an error?
Autorelease just means "this will be released at a later date". If you autorelease something three times, it will be released three times, later.
Instead of guessing, read through and understand the Memory Management Programming Guide before you do anything else. It will save you a ton of time and frustration.
You also asked, in the comments to another answer, why people use autorelease to begin with. Autorelease is necessary for a common case where you have to create a new object and return it. By the other rules of memory management, you would need to release the object at some point or it would be leaked, but if you release it before you return it, it will go away immediately.
There are two ways that you could deal with this: a) to have these methods return a new object which the caller is expected to release when it is done with the object, and b) to make sure that the object is released as soon as the caller is done with it.
The way Cocoa and Cocoa Touch handle this situation by convention is option b): to use autorelease pools, because you won't have to keep track of ownership except for the objects you explicitly create. Some people use autorelease for nearly everything instead of release, and this is a bit more inefficient than release, but more importantly it hides any useful distinctions you might make between release and autorelease when you're trying to read, navigate and understand the code.
As I said earlier, please read the Memory Management Programming Guide and all these questions will be answered. Better yet, if you just follow the simple rules listed in there, you won't have to think deep thoughts about every combination; there'll be a general rule to follow for your situation and the rule will work.
There's no error with autorelease - it just sets the object to be automatically released at a later time, which you don't necessarily have control over.
I try to always explicitly release my objects, unless I don't have a choice such as when returning a newly alloced/init-ed object from a method.
Actually when you create an object by using the following statement,
ClassA *obj = [[ClassA alloc]init ...];
Then you need to release that object, other wise it will be remain in that app and not useful by any other objects. Then the memory will be wasted.
So we have to release the object by [obj release];
in case some time we can't release at specific time. So we will put autorelease. If we do like that then the NSAutoReleasePool handle the release operation.
We can use any of the above.
Reagrds,
Satya.
No, it's not an error at all. Autorelease means that the object will be released at the end of the current Autorelease pool.
Look at your main.m class file (Every Cocoa/Cocoa Touch project gets it). You will see it has a method that looks a bit like this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
UIApplicationMain(.....);
[pool release];
UIApplicationMain starts your app's run loop. When you reach the end of it, (The application is closed) anything in the autorelease pool is dumped.
Now, if you impliement multithreading and you create your own Autorelease pools within the pool, you'll release the object when that pool is released.
The documentation on the method is here: http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/autorelease

Any way to check if an instance is still in memory?

Example: I have a view controller and get rid of it. But there's still an variable holding it's memory address. Accessing that results in EXEC_BAD_ACCESS. Of course. But: Is there any way to check if that variable is still valid? i.e. if it's still pointing to something that exists in memory?
You need to read this again:
Cocoa Memory Management Guidelines
In short, if you want something to stick around you must retain it.
If you want something to go away and you have previously retained it, you must release or autorelease it.
You must never call dealloc directly (except [super dealloc]; at the end of every one of your dealloc methods).
You must never release or autorelease an object that you did not retain.
Note that some methods do return retained objects that you must release. If you alloc an instance of a class, that implies a retain. If you copy and instance, the copy is retained.
If you are ever tempted to use the retainCount method, don't. It isn't useful. Only consider retain counts as a delta; if you add, you must subtract, but the absolute value is an implementation detail that should be ignored.
(In other words, even if there were ways to check for an object's validity definitively -- there aren't -- it would be the wrong answer.)
Oh, and use the Build and Analyze feature in Xcode. It does a very good -- but not quite perfect -- job of identifying memory management problems, amongst other things.
That's what the entire memory management model is set up for - if you call retain at the right times, and release and autorelease at the right times, that can't happen. You can use NSZombie to help you debug.
Use "NSZombieEnabled" break point.
For this reason only all strongly recommend us to use accessors. If your object is released anywhere, it will get assigned to nil, and there will be no harm if you call any API or method on Nil object. So please make a habit of using Accessors.
you just add this NSZombieEnabled Flag as an argument to your application in build settings. and enable it. Now you run your application in debug mode. If any such crash is about to occur, this breakpoint will show you which object is freed and where it is crashing.
Cheers,
Manjunath
If by variable, you mean whether the pointer to your object still references valid memory then:
MyClass *myVariable = [[MyClass alloc] init];
//Tons of stuff happens...
if (myVariable != nil)
//Do more stuff

Which iPhone OS memory management rules and how-to's do you know?

Currently I am jumping into the ice cold water called "memory management in iPhone OS".
Here's one rule i've learned:
Every time I see an alloc in my method, I will release that corresponding variable at the bottom of the method.
Every time I create an #property(...) in my header file which says copy or retain, I put a release message on that variable into the dealloc method.
Every time I have an IBOutlet, I do the same thing. Only exception: If the IBOutlet has something like #property(... assign), or in other words: If it has the assign keyword at all. Then I don't care about releasing it in the dealloc method.
I feel that there are many more good rules to know! Just write down what you have. Let's scrape them all together. Links to great descriptions are welcome, too.
Actually, any time you initialize an object and the method name includes "init" you are responsible for releasing it. If you create an object using a Class method that does not include the word "init" then you don't.
For example:
NSString *person = [NSString stringWithFormat:"My name is %#", name];
does not need a release. But:
Person *person = [[Person alloc] init];
needs a release (as you stated in your question). Likewise:
Person *person = [[Person alloc] initWithName:#"Matt"]];
also needs a release.
This is a convention, not a rule of the language, but you will find that it is true for all Apple-supplied APIs.
The rules I use
Release all objects you create using a method whose name begins "alloc" or "new" or contains "copy".
Release all objects you retain.
Do not release objects created using a +className convenience constructor. (The class creates it and is responsible for releasing it.)
Do not release objects you receive in other ways E.g.
mySprockets = [widget sprockets];
If you store an object you receive in an instance variable, retain it or copy it. (Unless it's a weak reference - just a pointer to another object, usually to avoid cyclical references.)
Received objects are valid within the method they are received in (generally) and are also valid if passed back to the invoker.
Some good links:
http://www.gehacktes.net/2009/02/iphone-programming-part-2-objective-c-memory-management/
http://mauvilasoftware.com/iphone_software_development/2008/01/iphone-memory-management-a-bri.html
Memory management can seem daunting when you're seeing segfaults spring from every seeming innocent line of code, but it's actually pretty easy once you get the hang of it. Spend a little time reading this page and then Apple's documentation, and you should be writing bug-free code in no time.
I tend to create only autoreleased objects, either by using a class method or by autoreleasing it immediately after creation, unless I can state a reason not to. For example:
I am assigning it to a member variable because I intend to hold onto it for a while.
I am only creating it to pass it on immediately to another method, and I send it a release message right after that method call.
For performance reasons, I need to free that memory before the nearest NSAutoreleasePool will be released, such as creating a large number of objects inside a loop or the objects are holding onto a large amount of data (e.g., images).
That way, I am less likely to leak objects. By default, I create them autoreleased, and when I make the deliberate decision not to autorelease them, I am immediately faced with the question of where they will be released.
For object properties, rather than releasing them in my dealloc method, I like to assign nil to them. That way, retained or copied properties are sent a release, while assigned properties are simply overwritten, and I don't have to update my dealloc method if I change the property to/from retained.

Understanding reference counting with Cocoa and Objective-C

I'm just beginning to have a look at Objective-C and Cocoa with a view to playing with the iPhone SDK. I'm reasonably comfortable with C's malloc and free concept, but Cocoa's references counting scheme has me rather confused. I'm told it's very elegant once you understand it, but I'm just not over the hump yet.
How do release, retain and autorelease work and what are the conventions about their use?
(Or failing that, what did you read which helped you get it?)
Let's start with retain and release; autorelease is really just a special case once you understand the basic concepts.
In Cocoa, each object keeps track of how many times it is being referenced (specifically, the NSObject base class implements this). By calling retain on an object, you are telling it that you want to up its reference count by one. By calling release, you tell the object you are letting go of it, and its reference count is decremented. If, after calling release, the reference count is now zero, then that object's memory is freed by the system.
The basic way this differs from malloc and free is that any given object doesn't need to worry about other parts of the system crashing because you've freed memory they were using. Assuming everyone is playing along and retaining/releasing according to the rules, when one piece of code retains and then releases the object, any other piece of code also referencing the object will be unaffected.
What can sometimes be confusing is knowing the circumstances under which you should call retain and release. My general rule of thumb is that if I want to hang on to an object for some length of time (if it's a member variable in a class, for instance), then I need to make sure the object's reference count knows about me. As described above, an object's reference count is incremented by calling retain. By convention, it is also incremented (set to 1, really) when the object is created with an "init" method. In either of these cases, it is my responsibility to call release on the object when I'm done with it. If I don't, there will be a memory leak.
Example of object creation:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Now for autorelease. Autorelease is used as a convenient (and sometimes necessary) way to tell the system to free this object up after a little while. From a plumbing perspective, when autorelease is called, the current thread's NSAutoreleasePool is alerted of the call. The NSAutoreleasePool now knows that once it gets an opportunity (after the current iteration of the event loop), it can call release on the object. From our perspective as programmers, it takes care of calling release for us, so we don't have to (and in fact, we shouldn't).
What's important to note is that (again, by convention) all object creation class methods return an autoreleased object. For example, in the following example, the variable "s" has a reference count of 1, but after the event loop completes, it will be destroyed.
NSString* s = [NSString stringWithString:#"Hello World"];
If you want to hang onto that string, you'd need to call retain explicitly, and then explicitly release it when you're done.
Consider the following (very contrived) bit of code, and you'll see a situation where autorelease is required:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:#"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
I realize all of this is a bit confusing - at some point, though, it will click. Here are a few references to get you going:
Apple's introduction to memory management.
Cocoa Programming for Mac OS X (4th Edition), by Aaron Hillegas - a very well written book with lots of great examples. It reads like a tutorial.
If you're truly diving in, you could head to Big Nerd Ranch. This is a training facility run by Aaron Hillegas - the author of the book mentioned above. I attended the Intro to Cocoa course there several years ago, and it was a great way to learn.
If you understand the process of retain/release then there are two golden rules that are "duh" obvious to established Cocoa programmers, but unfortunately are rarely spelled out this clearly for newcomers.
If a function which returns an object has alloc, create or copy in its name then the object is yours. You must call [object release] when you are finished with it. Or CFRelease(object), if it's a Core-Foundation object.
If it does NOT have one of these words in its name then the object belongs to someone else. You must call [object retain] if you wish to keep the object after the end of your function.
You would be well served to also follow this convention in functions you create yourself.
(Nitpickers: Yes, there are unfortunately a few API calls that are exceptions to these rules but they are rare).
If you're writing code for the desktop and you can target Mac OS X 10.5, you should at least look into using Objective-C garbage collection. It really will simplify most of your development — that's why Apple put all the effort into creating it in the first place, and making it perform well.
As for the memory management rules when not using GC:
If you create a new object using +alloc/+allocWithZone:, +new, -copy or -mutableCopy or if you -retain an object, you are taking ownership of it and must ensure it is sent -release.
If you receive an object in any other way, you are not the owner of it and should not ensure it is sent -release.
If you want to make sure an object is sent -release you can either send that yourself, or you can send the object -autorelease and the current autorelease pool will send it -release (once per received -autorelease) when the pool is drained.
Typically -autorelease is used as a way of ensuring that objects live for the length of the current event, but are cleaned up afterwards, as there is an autorelease pool that surrounds Cocoa's event processing. In Cocoa, it is far more common to return objects to a caller that are autoreleased than it is to return objets that the caller itself needs to release.
Objective-C uses Reference Counting, which means each Object has a reference count. When an object is created, it has a reference count of "1". Simply speaking, when an object is referred to (ie, stored somewhere), it gets "retained" which means its reference count is increased by one. When an object is no longer needed, it is "released" which means its reference count is decreased by one.
When an object's reference count is 0, the object is freed. This is basic reference counting.
For some languages, references are automatically increased and decreased, but objective-c is not one of those languages. Thus the programmer is responsible for retaining and releasing.
A typical way to write a method is:
id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
The problem of needing to remember to release any acquired resources inside of code is both tedious and error-prone. Objective-C introduces another concept aimed at making this much easier: Autorelease Pools. Autorelease pools are special objects that are installed on each thread. They are a fairly simple class, if you look up NSAutoreleasePool.
When an object gets an "autorelease" message sent to it, the object will look for any autorelease pools sitting on the stack for this current thread. It will add the object to the list as an object to send a "release" message to at some point in the future, which is generally when the pool itself is released.
Taking the code above, you can rewrite it to be shorter and easier to read by saying:
id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
Because the object is autoreleased, we no longer need to explicitly call "release" on it. This is because we know some autorelease pool will do it for us later.
Hopefully this helps. The Wikipedia article is pretty good about reference counting. More information about autorelease pools can be found here. Also note that if you are building for Mac OS X 10.5 and later, you can tell Xcode to build with garbage collection enabled, allowing you to completely ignore retain/release/autorelease.
Joshua (#6591) - The Garbage collection stuff in Mac OS X 10.5 seems pretty cool, but isn't available for the iPhone (or if you want your app to run on pre-10.5 versions of Mac OS X).
Also, if you're writing a library or something that might be reused, using the GC mode locks anyone using the code into also using the GC mode, so as I understand it, anyone trying to write widely reusable code tends to go for managing memory manually.
As ever, when people start trying to re-word the reference material they almost invariably get something wrong or provide an incomplete description.
Apple provides a complete description of Cocoa's memory management system in Memory Management Programming Guide for Cocoa, at the end of which there is a brief but accurate summary of the Memory Management Rules.
I'll not add to the specific of retain/release other than you might want to think about dropping $50 and getting the Hillegass book, but I would strongly suggest getting into using the Instruments tools very early in the development of your application (even your first one!). To do so, Run->Start with performance tools. I'd start with Leaks which is just one of many of the instruments available but will help to show you when you've forgot to release. It's quit daunting how much information you'll be presented with. But check out this tutorial to get up and going fast:
COCOA TUTORIAL: FIXING MEMORY LEAKS WITH INSTRUMENTS
Actually trying to force leaks might be a better way of, in turn, learning how to prevent them! Good luck ;)
Matt Dillard wrote:
return [[s autorelease] release];
Autorelease does not retain the object. Autorelease simply puts it in queue to be released later. You do not want to have a release statement there.
My usual collection of Cocoa memory management articles:
cocoa memory management
There's a free screencast available from the iDeveloperTV Network
Memory Management in Objective-C
NilObject's answer is a good start. Here's some supplemental info pertaining to manual memory management (required on the iPhone).
If you personally alloc/init an object, it comes with a reference count of 1. You are responsible for cleaning up after it when it's no longer needed, either by calling [foo release] or [foo autorelease]. release cleans it up right away, whereas autorelease adds the object to the autorelease pool, which will automatically release it at a later time.
autorelease is primarily for when you have a method that needs to return the object in question (so you can't manually release it, else you'll be returning a nil object) but you don't want to hold on to it, either.
If you acquire an object where you did not call alloc/init to get it -- for example:
foo = [NSString stringWithString:#"hello"];
but you want to hang on to this object, you need to call [foo retain]. Otherwise, it's possible it will get autoreleased and you'll be holding on to a nil reference (as it would in the above stringWithString example). When you no longer need it, call [foo release].
The answers above give clear restatements of what the documentation says; the problem most new people run into is the undocumented cases. For example:
Autorelease: docs say it will trigger a release "at some point in the future." WHEN?! Basically, you can count on the object being around until you exit your code back into the system event loop. The system MAY release the object any time after the current event cycle. (I think Matt said that, earlier.)
Static strings: NSString *foo = #"bar"; -- do you have to retain or release that? No. How about
-(void)getBar {
return #"bar";
}
...
NSString *foo = [self getBar]; // still no need to retain or release
The Creation Rule: If you created it, you own it, and are expected to release it.
In general, the way new Cocoa programmers get messed up is by not understanding which routines return an object with a retainCount > 0.
Here is a snippet from Very Simple Rules For Memory Management In Cocoa:
Retention Count rules
Within a given block, the use of -copy, -alloc and -retain should equal the use of -release and -autorelease.
Objects created using convenience constructors (e.g. NSString's stringWithString) are considered autoreleased.
Implement a -dealloc method to release the instancevariables you own
The 1st bullet says: if you called alloc (or new fooCopy), you need to call release on that object.
The 2nd bullet says: if you use a convenience constructor and you need the object to hang around (as with an image to be drawn later), you need to retain (and then later release) it.
The 3rd should be self-explanatory.
Lots of good information on cocoadev too:
MemoryManagement
RulesOfThumb
As several people mentioned already, Apple's Intro to Memory Management is by far the best place to start.
One useful link I haven't seen mentioned yet is Practical Memory Management. You'll find it in the middle of Apple's docs if you read through them, but it's worth direct linking. It's a brilliant executive summary of the memory management rules with examples and common mistakes (basically what other answers here are trying to explain, but not as well).