I have the following situation, which seems to cause my iPad application to leak memory.
I have a class with a string property...
#property(nonatomic,retain) NSString * synopsis;
I set the string property from some HTTP response, either from JSON or XML response.
At that point the retain count of the synopsis object is 1.
But I have this situation:
I save the synopsis to a local sqlite database, and then I want to release it from memory, but I have the situation where strangely, calling [synopsis release] from within my object does not decrement the retain count to 0.
(void) save
{
NSLog(#"synopsis before save retainCount=%d",[synopsis retainCount]);
[self saveToDb:synopsis withKey:#"synopsis"];
NSLog(#"synopsis after save retainCount=%d",[synopsis retainCount]);
[synopsis release];
NSLog(#"synopsis after release retainCount=%d",[synopsis retainCount]);
synopsis=nil;
}
In the console I get:
synopsis before save retainCount=1
synopsis after save retainCount=1
synopsis after release retainCount=1
How can this be possible? I get the same result running in simulator or on the device.
DON'T RELY ON RETAINCOUNT!
To humans, it's not an accurate measure of object ownership. You don't know what's calling retain and release behind the scenes in a framework.
Memory management in Cocoa is simple:
If you alloc/init or copy an object, make sure you call release on it at some point.
If you want to keep an object around, call retain -- but make sure to call release at some point, too.
Your third NSLog probably calls retainCount on a deallocated object.
The fact, that you see a value of 1 can have three reasons:
There's some other object at the same address now, that has a retain count of one.
(more likely) The deallocated object is still there. It responds to the message by returning the retain count, which would be one because it never was decremented to zero (no need to do that ever, since a deallocated object does not need a valid retain count).
The object is still there and has some custom memory management, preventing retainCount from being decremented.
Edit:
To check deallocation of objects (if you want to be sure), you could always override dealloc and set a breakpoint or put a log message there.
This might help. From the docs about retainCount:
Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.
To understand the fundamental rules of memory management that you must abide by, read “Memory Management Rules”. To diagnose memory management problems, use a suitable tool:
• The LLVM/Clang Static analyzer can typically find memory management problems even before you run your program.
• The Object Alloc instrument in the Instruments application (see Instruments User Guide) can track object allocation and destruction.
• Shark (see Shark User Guide) also profiles memory allocations (amongst numerous other aspects of your program).
Related
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"];
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 !!!
I have managed to get myself confused about some elements of memory management. I am new to objective-c, and memory managed languages generally.
I have read the memory management guidelines, but I remain confused about a couple of things.
1) Is there any need to clean up ivars, and method variables that are not retained by any object. For instance
-(void) someMethod{
int count = 100;
for (int i=0; i <count; i++) {
NSLog(#"Count = %d", i);
}
}
What happens to the "count" var after the method is complete?
If a method allocates lots of temporary variables, do those get removed from memory as long as they are not unreleased, alloc'd objects? Or do i need to set them to nil in some way?
2) If i have a static variable, for instance an NSString, do I have to do anything for that to be removed from memory when the class is dealloced?
3) I have noticed that NSStrings seem to have a retainCount of 2147483647 which wikipedia tells me is the max value for a 32 bit signed integer.
http://en.wikipedia.org/wiki/2147483647
myString retainCount = 2147483647
-(void) someMethod{
NSString *myString = #"testString";
NSLog(#"myString retainCount = %d", [myString retainCount]);
// logs: myString retainCount = 2147483647
}
What happens to this at the end of the method? Does this memory ever get emptied? The string is not being referenced by anything. My understanding is that the #"" convenience method for NSString returns an autoreleased object, but whats the point of autoreleasing something with a retainCount of 2147483647 anyway? In that case, whats the point of retaining or releasing ANY NSString?
I am well aware that retainCount should be ignored, but it just bugs me not to know what's going on here.
4) Does this matter at all? I know that the memory associated with an NSString isn't much to write home about, but I want to be a good memory management citizen, and I'm more interested in best practices than anything else.
Retain/release only matters for objects, not int, bool, float, double or other built-ins. So use it for id or other classes that you hold a pointer to an object. In your example, count doesn't need to be retained or released. It is allocated on the stack which is automatically cleaned up when the function returns.
You do need to deal with any local objects you alloc. Those are created with a retainCount set to 1, so you need to either hold on to them for later or release them. Most Cocoa functions (that don't start with copy or alloc) return an object that is autoreleased. This means that they will have release called on them later -- you can only hold these after the function if you call retain on them. If you want them to be cleaned up, you don't need to do anything (calling release would result in too many release calls).
If you have a static variable pointing to an object, then it is not touched when objects of that class are dealloced. If you want it to be released, you have to call release on it. If the static is an int, bool, or other built-in, you don't (can't) call release on it. That's part of the global memory of your app.
NSStrings that are set to string literals should not have release called on them. The retainCount is meaningless for them. That value is also -1 for signed int values.
If you do this -- [[NSString alloc] initCallHere:etc] -- you have to call release on it. Most of the time you get strings, you don't use alloc, so you don't need to call release. If you retain one, you need to call release.
Yes, it does matter. Over time leaks will cause the iPhone to kill your app.
You don't need to worry about count cause it's an integer, a primitive data type, not an object.
I've read that those just go away upon app termination or if you explicitly release them.
You are right in that you should not worry about the retain count in that way. Cocoa automatically gives #"" (NSConstantString objects) the absolute highest retain value so that they cannot be de-allocated.
You are over complicating the subject. The point of the three guidelines is so that you know that you only have to worry about memory management in three specific situations. Apple gives you these guidelines so that one doesn't have to worry about the specific internals for every single class (like manually tracking retainCount), not to mention that sometimes Cocoa does things differently (as with NSConstantString). As long as you remember these guidelines, you really don't have to know the very gritty details of what's going on underneath (of course, an understanding of the retain count concept helps, but compare this to manually tracking it).
I don't know which guide you read specifically, but if you haven't given this one a try, I highly recommend it. It summarizes the three guidelines in a concise and direct manner.
The Cocoa memory management rules only cover Objective C objects.
Local variables (non-static) are cleaned up when any subroutine or method exits (actually the stack memory is just reused/overwritten by subsequent subroutines or methods in the same thread). Constants which require memory (strings) and static variables are cleaned up when the app is torn down by the OS after it exits. Manually malloc'd memory is cleaned up when you manually free it.
But any object you alloc or retain: (whether assigned to an ivar, local, global, static, etc.) has to managed like any other object. Be careful assigning objects to global variables, unless you are really good at retain count management.
if I release a variable more than it should be, would that be a problem? I cannot determine the retain count ahead of time.
Foreword
The retain count should be considered more of a theoretical offset. You should never care about what the value currently is, just how your actions will offset it. For example, when you add an object to an array, you have offset its retain count by +1, and when you remove an object from an array, you have offset its retain count by −1. When you're completely done with an object, its retain count offset (relative to you) should be 0. What its retain count actually is does not matter, as long as you fulfil your obligations to manage the object appropriately.
Inspecting the retain count explicitly will often not show what you expect. This could be because of optimisations under the hood. Cocoa relies on the developer conforming to the memory management guidelines. Follow these very simple rules, and do not worry about the explicit value of retainCount.
WRT the question
Over-releasing an object (sending it too many release messages) can—and usually does—result in premature deallocation of that object. Any messages that get sent to the address where the deallocated object used to be will usually crash your application. The dumbed-down rules of thumb are:
Sending a alloc, new, retain, copy (or any method with copy in its name) will give you an object with a retain count offset by +1.
Sending release will offset that objects retain count by −1.
Balance each +1 with a −1 and that's it!
Furthermore
If you are developing a framework or library and you are returning objects to users of your framework, don't try to prevent errors in their code by over-retaining objects. Their obligations are exactly the same as yours, and if they break your framework from poor memory management then that is a bug in their code, not yours.
Don't worry about the retainCount. Only send release to an object that you own. If you get an object by sending alloc to a class, or send an object a retain, copy or mutableCopy message, then you own the object and are responsible for sending it a release message at some time in the future.
It's all explained in the Memory Management Guide.
Please please please do not over release an object ever.
While you're developing your app, it's wise to set the environment variable
MallocScribble="YES"
This will immediately overwrite the pointer for a free'd object to 0x555 so you'll crash where you wouldn't before. Also break on obj-c exceptions! These two settings enabled will help make your app more robust.
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).