Tutorial :With obj-c on the iPhone, is there any harm in autoreleasing everything instead of releasing?



Question:

With obj-c on the iPhone, is there any harm in autoreleasing everything instead of releasing?

Eg, this code:

NSString *recipe = [[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)];  [arr addObject:recipe];  [recipe release];  

Can be shortened to two lines by autoreleasing the recipe nsstring when i create it:

NSString *recipe = [[[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)] autorelease];  [arr addObject:recipe];  

Are there any drawbacks to this? I find it suits my coding style better. Thanks all.


Solution:1

The drawback is that the objects get released later. In most cases this won't be a problem but if you allocate and autorelease thousands of objects in a tight loop this overhead can add up to a point where it impacts performance or even causes your app to run out of memory.

In any case, you might want to use:

[NSString stringWithUTF8String:sqlite3_column_text(dbps,0)];  

instead of

[[[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)] autorelease];  


Solution:2

If the object does not have a scope outside the function it is used, you should always release it in order to minimize the amount of memory consumed by your application.

If you let the object stick around until the autorelease pool kicks in, a lot of unneeded memory may need to be allocated. This is especially important with iOS 4 and fast app switching, where memory is also allocated to apps in the background.

The lower your own memory footprint is, the bigger a chance there is that your application will not be terminated when in the background in case memory gets tight.


Solution:3

Here is my understanding on the subject, I'm sure I'll get downvoted to death if I say anything wrong ;)

  1. Generally speaking, in tight loops, init + release will be faster than autorelease. Most of the time performance is not an issue
  2. You may not actually want to autorelease at all times. If you want an object to stick around, you'll need to manually release or stick your autoreleased obj in a property with a retain so that you can get at it later otherwise your obj will be released as soon as it goes out of scope
  3. With manual init + release you have more fine grained control over what is happening, this may be useful for advanced multi-threaded scenarios (especially now that GCD is pervasive)
  4. autorelease is probably fine most of the time so long as you understand how reference counting works, but do not treat it like a silver bullet. You can still leak plenty of memory using autorelease incorrectly.


Solution:4

I'll turn the question around: The main disadvantage with release is that it's very easy to forget. Assignment to a local or to an instance variable look pretty much identical (they're entirely identical if you don't assign in an initializer):

  • Foo * a = [[Foo alloc] init];
  • myFoo = [[Foo alloc] init];

This, and similar issues, leads to a bunch of potential problems:

  • When you copy-and-paste code, will you forget a release?
  • When you change between local and instance variables, will you remember to add/remove the release?
  • If an exception is thrown, does the code leak? (This is almost always true, but it is traditional to not care about exceptions in Obj-C.)

Personally, the overhead of a memory leak when you refactor code is worse than the overhead of a few autoreleased objects. I occasionally refactor code so it looks like this:

FooView * v = [[[FooView alloc] initWithFrame:CGRectZero] autorelease];  // set up v...  myFoo = [v retain];  
  • Local variables are marginally more efficient.
  • If you decide that you don't need the instance variable anymore, you just need to comment out one line.
  • Views are pretty heavyweight, so the autorelease overhead isn't going to matter much

For completeness, if you're doing a bunch of things in a loop (e.g. test code), you can autorelease at the end of every iteration with something like this:

for (size_t n = 100000; n--; ) {    NSAutoreleasePool * pool = [NSAutoreleasePool new];    // ... allocate and autorelease some stuff ...    [pool release]; pool = nil;  }  

If you're worried about efficiency, you can gain significant speedups using (e.g.) CFString functions â€" the Objective-C overhead is pretty significant for small strings.


Solution:5

Problem is when you do autorelease you're not actually releasing the object but adding it to the current autorelease pool. Object will be effectively released when you release that pool which is done every time through the main loop .

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  int retVal = UIApplicationMain(argc, argv, nil, nil);  [pool release];  

You can create you're own autorelease pool but I'm not sure it would be better than simply use release.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »