问题
When you catch an exception in an ObjC @catch
block, what is the lifecycle of that exception object? I know I can safely use it inside the block, but what if I want to use it again after the block, like this?
NSException * exception = nil;
@try {
// do something risky
} @catch(NSException * e) {
exception = e;
}
if (exception) {
NSLog(@"Caught exception: %@", exception);
}
Can I safely stash the reference into another local? Should I be retain, autorelease
ing it for safety? Can I retain it and hold onto it indefinitely?
(It does seem to work OK if I assign to the local, or retain and use later, but the docs don't really discuss where this object "comes from" in terms of ownership, or if it's special, so I was looking for more clarity.)
回答1:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Exceptions/Tasks/HandlingExceptions.html
Almost all NSException objects (and other types of exception objects) are created autoreleased, which assigns them to the nearest (in scope) autorelease pool. When that pool is released, the exception is destroyed.
Also, I'm pretty sure that somewhere in the memory programming guide, they mention that methods without new
or alloc
or copy
in their names always return autoreleased objects by convention. NSException's methods qualify for that.
Slightly related (not NSException but NSError):
If you create an NSError object with initWithDomain:code:userInfo:, you should send autorelease to it before you return it to the caller.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html
回答2:
@catch
blocks do absolutely nothing for lifecycle. The implicit contract here is an NSException
object that is -raise
'd or @throw
n should be an autoreleased object. This means that in the @catch
block, the NSException
that you are given is an autoreleased object, just like any autoreleased object you might get from a method call. You can safely stash it in a local and reference it after the @catch
block.
回答3:
NSException inherits from NSObject
, so you can probably do all the typical things one would do with any other Objective C object.
However, I'd recommend not doing anything with it outside of your thread. This O'Reilly article about Exceptions suggests:
Do not use a
release
or anautorelease
message to dispose an NSException. All instances of NSException are placed in the main autorelease pool. Manually disposing an instance will result in aSIGSEGV
error.Do not use a
retain
message to preserve an NSException. It will prevent the autorelease pool from disposing the instance. This will only result in a subtle memory leak.
... and some other useful helpful hints on these objects.
回答4:
NSException
adopts NSCopying
(and NSCoding
fwiw). If you are in a case of questionable lifetime and want to make that explicit, a copy would be ideal.
I'm stopping there - unwinding and cocoa idioms flow against each other.
来源:https://stackoverflow.com/questions/8364834/what-is-the-lifecycle-of-an-object-caught-in-a-catch-block