I have been programming on iPhone for quite sometime and have had bad experiences with memory management. I was wondering if the following way is a good way to release memory.
int count = [someObject retainCount];
for (int i = 0; i < count; i ++)
{
[someObject release];
}
This method was an act of desperation in a few situations (particularly UIWebViews
) I had faced. The variable's retainCount is reduced to zero which will release the memory being used by it. The method is a little dirty but are there any bottlenecks associated with it?
You should not rely on the retainCount
because there are possibility of retaining the object by iOS
frameworks,
Read below what Apple say 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:
This code is an absolute no-go. It just hides your programming mistakes - and it does so in a very bad manner.
Please learn proper memory management. There is no substitute.
Here is the memory management programming guide. It is worth reading more than once.
As others have mentioned, -retainCount
is virtually useless. When you're new to the memory management/reference counting in Objective-C, it can sometimes be tempting to try to use -retainCount
to help understand how reference counting works, but in reality, it can be (seemingly) confusing at best.
The code you posted is potentially dangerous, in and of itself, depending on your surrounding context of how someObject
is being used. It can also be dangerous when applied to other situations you weren't expecting. Take constant NSString
s created using the @"a string"
compiler directive: these strings are created and are designed to never be released. So applying your code like in the following example would result in an infinite loop:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *string = @"theString";
NSLog(@"retainCount == %lu", (unsigned long)[string retainCount]);
for (NSUInteger i = 0; i < [string retainCount]; i++) {
[string release];
}
[pool drain];
return 0;
}
This prints:
2011-06-30 08:40:16.287 retainCount[35505:a0f] retainCount == 1152921504606846975
and then goes into an infinite loop.
I cannot say NO emphatically enough!
Take this example of your code in action :
// Create an autoreleased object
MyObject *myObject = [[[MyObject alloc] init] autorelease];
// Run your code to make it dealloc itself
int count = [myObject retainCount];
for (int i = 0; i < count; i ++)
[myObject release];
Your code would force myObject
to be dealloced.
However, myObject
has been put into the autorelease pool as well - as soon as the pool started to release it's objects your app would crash because myObject
doesn't exist anymore!
The rule is simple : Call release each time you use init, new or copy. Otherwise it's not your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With