In Apple's example code, the method tableView:cellForRowAtIndexPath: of a UITableViewDataSource returns a cell with a retain count of 1; it allocs it, but doesn't autorelease it. However, the static analyzer complains that this violates the Cocoa naming conventions, since the method name doesn't start with 'new', etc. The documentation doesn't mention the expected retain count of the cell. What retain count should the cell have? Should I file a bug against the documentation? Thanks.
EDIT: The example code I looked at does autorelease it, and my eye somehow skipped over it. Sorry to waste your time. Thanks for the responses.
Further edit: A bug should probably be filed against Clang if questioners are going to get jumped for using its terminology in a question. :-)
The value of retainCount is not really important (it can go up and down for seemingly unknown reasons). But cells created in tableView:cellForRowAtIndexPath: should be autoreleased. What example code are you looking at?
Which example code? MyTableViewController.m returns either [tableView dequeueReusableCellWithIdentifier:kCellID] or [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease].
If the example code does something different, it's probably wrong. Nearly all methods follow Objective-C naming conventions; the ones that don't tend to be explicitly documented.
Retain count is always at least 1. You won't ever get back an object with a retain count less than that, it would be an ex-object already. Please please please don't draw conclusions from retain counts, or have expectations about them, or even ever look at them. Never never never never never.
There may possibly be dodgy example code here and there that does the wrong thing. Ignore it. Do the right thing and don't fret yourself about the rest.
In fact, DO NOT USE THE retainCount at all. I got so confused and it lead me into the totally wrong direction and I wasted literally days hunting down wrong leaks. It means ABSOLUTELY NOTHING if the count goes up or down! Don't waste a second dealing with it.
It's much better to use the Leak or Zombie tools!
(ps also thanks to walkytalky - as I just see he also answered this one!)
Don't worry about the retain count. You alloc a UITableViewCell in your cellForRowAtIndexPath:, which means you have to release it or you have a memory leak. You can't release it because you have to return the cell, have the table view draw it as a subview, then release it. Therefore you autorelease it to have the autorelease pool release it later. When you return it, it hasn't been released yet, but gets released later by the system (you've simply relinquished ownership of it, which is what you want, because you don't maintain a reference to the cell after it's returned from the function).
Related
Reading source code of my current project, I see:
[self retain]
in one class, in its init method.
I don't understand exactly the reason.
Reading memory management rules from Apple, I don't see anything about this, and I don't see any hypothetical [self release].
The object is asserting ownership of itself when it is initialised. The only reason I can see that this might be useful is if the object needs to guarantee its own existence until some event has happened. For example, it might run a timer and then release itself when the timer expires.
If it's not documented and there is no corresponding release, it's probably a bug.
Best guess is that the person writing the code had a retain error and this was a "quick fix" around the real problem.
This seems to be probably an error, usually it's not up to the object to retain himself.
I see only one special case: delegate and notification, where you have to be much more careful about your life cycle, but even if this case, release/retain should not be done in the object itself.
Note to Erick:
In case of UIAlert, you can release it before it has been destroyed because the view has been but in the view hiercarchy, and then referenced. So the view will be automatically destroyed when it will be removed from the view hierarchy
It's not wrong to retain self. But seeing it in an init method sounds suspicious. I can't think of a good example of where that would be a good thing to do. Also though, with ARC, you can't even do that so you'd have to think of a better way of doing things. In general, if an object is required to be alive then there would be another object that is holding onto it. Self retaining objects are prone to errors where they will never be released.
If I recall correctly some classes use the self-retain to avoid pre-mature releasing. I would say it's not exactly best practice, but if you know the rules of the game (in this case Obj-C) you can break them (sometimes).
if you have some object, it's like it have healts/ lives. when you created it , it have one live. and. function 'retain' increasing his number of lives +1, release function decreasing his number of lives -1, dealloc decreasing too, alloc increasing
The question is simple. Do I need to release a NSLocalizedString? For instance:
NSString *internetMessageTitle = NSLocalizedString(
#"You are currently not connected to a internet network"
#"Title of the message that tells the user there is no internet network");
Because I did this:
NSLog(#"Retain count of InternetMessageTitle is: %d",
[internetMessage retainCount]);
But it prints a retain count of 2. However I have read that the retainCount attribute is not very reliable. Should I release it twice?
And yes I have read the memory management rules and guide of the documentation but I don't see here any indication of NARC (NewAllocRetainCopy). I am still a beginner so I don't really know how NSLocalizedString makes strings.
Thank you!
EDIT1: I use this variable in a UIAlertView I don't know if the retainCount is increased there when I use it. And even when the alert is not used (inside an if, and if the if is skipped it isn't used) the retainCount is still 2 according to NSLog.
No, you must not release it. If you check how NSLocalizedString is defined you'll see:
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]
That its normally a call to NSBundle's method that returns autoreleased string
I use this variable in a UIAlertView
I don't know if the retainCount is
increased there when I use it. And
even when the alert is not used
(inside an if, and if the if is
skipped it isn't used) the retainCount
is still 2 according to NSLog.
Yes, labels in UIAlert retain their content strings, but you should not worry about that - they will release them when get destroyed.
As you say, there's no NARC -- so you already know the answer is no.
And what you've read about retain counts? Heed it. Never look at the retain count as useful info. Never look at it all.
And FFS don't do something insane like calling release on an object several times just because you think it has a retain count > 1. That stuff is absolutely guaranteed to mess you up.
The Cocoa memory management rules are very simple. There's only one of consequence: all alloc/new*/*copy* calls must be balanced by a call to auto-/release. You're not calling a method or function named "alloc", starting with "new" or containing "copy", thus you shouldn't release.
Even simpler than following the memory rules is to use properties (object or class) when possible.
I am getting a leak on this line and I'm not sure why...
weather.condition = [weather.condition lowercaseString];
weather is a NSMutableArray with a load of NSStrings in? Is there anything obviously wrong with this line or is it a bigger issue?
Thanks
One thing you have to learn about detecting memory leaks, is that leaks doesn't detect the line the leak occurs on per say, it detects where the object that is leaking was retained/copied/created. You need to look elsewhere for the actual leak, posting more code would be helpful. I'll update this answer if you do. Please comment below to indicate you've updated the answer with more code.
I remember i had this problem when i was using stringByReplacingOccurrencesOfString and i had to declare a new string to hold it in, rather than perform it on itself if that makes any sense!:)
If weather.condition is a synthesized retain property, then you could probably get away with that statement without a leak because the synthesized setCondition method will check to see if there is a value assigned to condition, and release it. If you wrote the setCondition method, you are responsible for managing the memory associated with condition.
I have been looking through the questions asked on StackOverflow, but there are so many about memory management in Objective-C that I couldn't find the answer I was looking for.
The question is if it is ok (and recommnded) to call autorelease before adding a newly created object to a collection (like NSMutableArray)? Or should I release it explicitly after adding it. (I know NSMutableArray willl retain the object)
This illustrates my question:
Scenario A (autorelease):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
}
Scenario B (explicit release):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
[obj release];
}
I assume both are correct, but I am not sure, and I sure don't know what the preffered way is.
Can the Objective-C gurus shed some light on this?
IMHO, which way is 'right' is a matter of preference. I don't disagree with the responders who advocate not using autorelease, but my preference is to use autorelease unless there is an overwhelmingly compelling reason not to. I'll list my reasons and you can decide whether or not their appropriate to your style of programming.
As Chuck pointed out, there is a semi-urban legend that there's some kind of overhead to using autorelease pools. This could not be further from the truth, and this comes from countless hours spent using Shark.app to squeeze the last bit of performance out of code. Trying to optimize for this is deep in to "premature optimization" territory. If, and only if, Shark.app gives you hard data that this might be a problem should you even consider looking in to it.
As others pointed out, an autoreleased object is "released at some later point". This means they linger around, taking up memory, until that "later point" rolls around. For "most" cases, this is at the bottom of an event processing pass before the run loop sleeps until the next event (timer, user clicking something, etc).
Occasionally, though, you will need to get rid of those temporary objects sooner, rather than later. For example, you need to process a huge, multi-megabyte file, or tens of thousands of rows from a database. When this happens, you'll need to place a NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; at a well chosen point, followed by a [pool release]; at the bottom. This almost always happens in some kind of "loop batch processing", so it's usually at the start and bottom of some critical loop. Again, this should be evidence based, not hunch based. Instrument.app's ObjectAlloc is what you use to find these trouble spots.
The main reason why I prefer autorelease to release, though, is that it is much easier to write leak-free programs. In short, if you choose to go the release route, you need to guarantee that release is eventually sent to obj, under all circumstances. While this seems like it might be simple, it is actually surprisingly hard to do in practice. Take your example, for instance:
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
// Assume a few more lines of work....
[obj release];
Now imagine that for some reason, something, somewhere, subtly violates your assumption that array is mutable, maybe as the result of using some method to process the results, and the returned array containing the processed results was created as a NSArray. When you send addObject: to that immutable NSArray, an exception will be thrown, and you will never send obj its release message. Or maybe something goes wrong somewhere between when obj was allocd and the required call to release, like you check some condition and return() immediately by mistake because it slipped your mind that that call to release later on must take place.
You have just leaked an object. And probably signed yourself up to several days of trying to find out where and why it is your leaking it. From experience, you will spend many hours looking at that code above, convinced that it could not possibly be the source of the leak because you very clearly send obj a release. Then, after several days, you will experience what can only be described as a religious epiphany as you are enlightened to the cause of the problem.
Consider the autorelease case:
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
// Assume a few more lines of work....
Now, it no longer matters what happens because it's virtually impossible to leak obj accidentally, even under extremely unusual or exceptional corner cases.
Both are correct and will work as you're expecting them to.
I personally prefer to use the latter method, but only because I like to be explicit about when objects get released. By autoreleasing the object, all we're doing is saying "this object will get released at some arbitrary point in the future." That means you can put the autoreleased object into the array, destroy the array, and the object might (probably) still exist.
With the latter method, the object would get destroyed immediately with the array (providing that nothing else has come along and retained it in the meantime). If I'm in a memory-constrained environment (say, the iPhone) where I need to be careful about how much memory I'm using, I'll use the latter method just so I don't have so many objects lingering in an NSAutoreleasePool somewhere. If memory usage isn't a big concern for you (and it usually isn't for me, either), then either method is totally acceptable.
They are both correct but B may be preferred because it has no overhead at all. Autorelease causes the autorelease pool to take charge of the object. This has a very slight overhead which, of course, gets multiplied by the number of objects involved.
So with one object A and B are more or less the same but definitely don't use A in scenarios with lots of objects to add to the array.
In different situations autoreleasing may delay and accumulate the freeing of many objects at the end of the thread. This may be sub-optimal. Take care that anyway autoreleasing happens a lot without explicit intervention. For example many getters are implemented this way:
return [[myObject retain] autorelease];
so whenever you call the getter you add an object to the autorelease pool.
You can send the autorelease message at any point, because it isn't acted on until the application's message loop repeats (i.e. until all your methods have finished executing in response to user input).
http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text
You have alloc'ed the object, then it's your job to release it at some point. Both code snippets work merely the same, correct way, with the autorelease way being the potentionally slower counterpart.
Personally speaking, I prefer the autorelease way, since it's just easier to type and almost never is a bottleneck.
They're both OK. Some people will tell you to avoid autorelease because of "overhead" or some such thing, but the truth is, there is practically no overhead. Go ahead and benchmark it and try to find the "overhead." The only reason you'd avoid it is in a memory-starved situation like on the iPhone. On OS X, you have practically unlimited memory, so it isn't going to make much of a difference. Just use whichever is most convenient for you.
I prefer A (autoreleasing) for brevity and "safety", as johne calls it. It simplifies my code, and I've never run into problems with it.
That is, until today: I had a problem with autoreleasing a block before adding it to an array. See my stackoverflow question:
[myArray addObject:[[objcBlock copy] autorelease]] crashes on dealloc'ing the array (Update: Turns out the problem was elsewhere in my code, but still, there was a subtle difference in behavior with autorelease…)
I have a UIViewController which has a retainCount of 3 the moment I instantiate it. That stirs me as terribly incorrect. What's the best way of figuring out who bumped up the retainCount to 3? I'd imagine instantiating the object should give the pointer 1, then I suppose maybe pushing it onto the UINavigationController's stack might bump it up one (not sure about that though?), but the third.. is a mystery.
Adam is right that you shouldn't be overly concerned about retain counts.
But if you ever have a legitimate need for solving such a mystery, a good technique is to subclass the affected class just so you can add overrides to the memory-management methods.
E.g. in a subclass of UIViewController, you could implement:
- (id) retain
{
// Break here to see who is retaining me.
return [super retain];
}
Don't ever rely on retain counts directly. What's happened is that during the initialization process, some piece of code has retained and autoreleased the object. Because you can't tell how many times an object has been autoreleased, you don't actually know what the real retain count is.
Retain counts should only be used as a debugging aid, never as program control flow.
As long as you follow all of the rules laid out in the Memory Management Programming Guide for Cocoa, you won't have problems.
What's the best way of figuring out who bumped up the retainCount to 3?
That's approaching the problem from the wrong angle. This will confuse you and will lead you astray (and probably right past) the actual problem, when indeed there is one.
Better to think about who owns the object. Do you intend to keep the object around as the value of one of your own properties? If so, then you are one of its owners. If not, then you aren't. If you pass the object to another object to store in one of its properties, then that other object is also an owner.
These ownerships are just relationships, so it's really easy to keep them straight in your head.
“This is one of my controllers. It owns the root objects of my model and one or more view[ controller]s.”
“This is a view. It owns some parts of my model.”
“This is part of my model. It owns primitive objects only.”
“This is another part of my model. It owns some primitive objects and some other bits of model.”
If you have a solid grasp of your ownerships, then you cannot write a memory leak except by forgetting a release or autorelease message (which can happen to anyone), and you will almost certainly not write a cyclic retention (two objects retaining each other) except knowingly and with copious comments and #warnings.
If you haven't worked out your ownerships, then you have probably written one or more memory leaks or cyclic retentions that you don't know about.
Edit: And to answer the actual question, the best way to figure out what has retained—and, possibly, subsequently autoreleased—an object is to use Instruments's Allocations instrument. With it, you can look at the history of any object to see every allocation, retain, autorelease, release, and deallocation of its address.
It's not a 100% solution, but the LLVM Clang Static Analyzer can be a big help in tracking down incorrect manual memory management usage. Between the Static Analyzer and MallocDebug, you can get to be a pro at tracking down memory management issues very quickly. BTW, even though Instruments is the new hotness, I find MallocDebug far more reliable.
You can find the LLVM Clang Static Analyzer here: LLVM/Clang Static Analyzer