views:

79

answers:

2

I have a method which allocates an object and then releases it at the end. In between, the method calls another method which could possibly raise an exception, and the exception will probably be caught by the method calling my method. If this happens, the object will never get released (or will it?). How should I prevent this from happening?

+2  A: 

You could always auto-release it before calling methods that possibly throw - that way you can be sure it will be released wether an exception will be thrown or not.

If that is not sensible for some reason, you could do the release in a @finally block1:

A @finally block contains code that must be executed whether an exception is thrown or not.

Note that using a @finally block without @catch is fine:

Resource *resource = [[Resource alloc] init];
@try {
    [obj someMethodThatMayThrow];
}
@finally {
    [resource release];
}
Georg Fritzsche
I am writing a library that I am going to release for other people to use, and I am not sure if it is okay to add stuff to their autorelease pools. Is it?
Adrian
Good question. If you expect to add oversized amounts to them i'd go for the release on `@finally` or add an inner pool on entry into the library - but then i haven't dealt with this situation before.
Georg Fritzsche
Thanks, another question: How would I do the @finally thing? I tried `@try { ... } @finally { ... }`, but the @finally block isn't executing.
Adrian
That is weird, `@finally` should always be executed - it even wins over `return`. Added an example, does that clear it up?
Georg Fritzsche
Yes, thanks! I was trying to `NSLog` in the `@finally` to see if it worked. That's why I thought it didn't.
Adrian
Short answer; don't throw exceptions unless they are fatal.
bbum
+2  A: 

Do not throw exceptions for anything but fatal, non-recoverable, errors

That is the Cocoa design pattern employed across the frameworks and system. If you decide you want to use exceptions for flow control then:

  • you are going against the Cocoa pattern and your code will be a misfit amongst the system APIs

  • if there are any frames in the system frameworks across which the exception was thrown, those frameworks will be left in an undefined state

Exceptions in Mac OS X and iOS are used only to indicate programmer error; to indicate that the app has entered into a state for which recovery isn't possible. Don't waste your time trying to support exceptions beyond that mode, you'll just be wasting your time and creating code that doesn't work like the system frameworks.

Note that throwing an exception on iOS is actually quite expensive (both CPU and memory). As well, @finally doesn't come for free, either, though the overhead of @finally is relatively minor by comparison.

bbum
So, what should I do when something doesn't work?
Adrian
If an exception is thrown, it should be treated like a crash. Once an exception is thrown by the frameworks, it is because the state is irrecoverable.
bbum