It is unsafe to throw exceptions in circumstances where resources are not automatically managed. This is the case of the Cocoa framework (and neighbor frameworks), as they use manual reference counting.
If you throw an exception, any release
call you skip over by unwinding the stack will result in a leak. This should limit you tothrowing only if you're certain that you're not going to recover since all resources are returned to the OS when a process quits.
Unfortunately, NSRunLoop
s tend to catch all exceptions that propagate to them, so if you throw during an event, you'll resume to the next event. This is, obviously, very bad. Therefore, it's better that you simply don't throw.
This problem is diminished if you use garbage-collected Objective-C, as any resource represented by an Objective-C object will be properly released. However, C resources (such as file descriptors or malloc
-allocated memory) that are not wrapped in an Objective-C object will still leak.
So, all in all, don't throw.
The Cocoa API has several workarounds to this, as you mentioned. Returning nil
and the NSError**
pattern are two of them.
Clarifications for ARC
ARC users can choose to enable or disable full exception safety. When exception safety is enabled, ARC will generate code to release strong references when their scope is killed, making it safe to use exception in your code. ARC will not patch external libraries to enable exception support in them, so you should be careful where you throw (and especially where you catch), even with exception support enabled in your program.
ARC exception support can be enabled with -fobjc-arc-exceptions
or disabled with -fno-objc-arc-exceptions
. By default, it is disabled in Objective-C but enabled in Objective-C++.
Full exception safety in Objective-C is disabled by default because the Clang authors assume that Objective-C programs will not recover from an exception anyways, and because there is a large code size cost and a small performance penalty associated to that cleanup. In Objective-C++, on the other hand, C++ already introduces a lot of cleanup code, and people are much more likely to actually need exception-safety.
This is all from the ARC specification on the LLVM website.