2011-12-03 47 views
4

当您在ObjC @catch块中捕获到异常时,该异常对象的生命周期是什么?我知道我可以在块内安全地使用它,但是如果我想在块之后再次使用它,像这样?@catch块中捕获的对象的生命周期是什么?

NSException * exception = nil; 
@try { 
    // do something risky 
} @catch(NSException * e) { 
    exception = e; 
} 

if (exception) { 
    NSLog(@"Caught exception: %@", exception); 
} 

我可以放心地藏匿参考到另一个地方?为了安全起见,我应该做些什么?我可以保留它并无限期地保持它吗?

(如果我将其分配给本地,或者稍后保留并使用,但文档没有真正讨论此对象“来自”所有权或它是否特殊,那么似乎工作正常我正在寻找更多的清晰度。)

回答

0

NSException继承自NSObject,所以你可以做所有其他Objective C对象的典型做法。

不过,我建议你没有做任何事的你的线程之外。 This O'Reilly article about Exceptions提示:

不要使用releaseautorelease消息处置的 NSException。 NSException的所有实例都放置在主要的 自动释放池中。手动处理实例将导致错误 SIGSEGV

不要使用retain消息保留的NSException。 它会阻止autorelease池处置实例。这 只会导致一个微妙的内存泄漏。

...和对这些对象的一些其他有用的有用的提示。

+1

从书的建议好像没用。这只是描述了正常的内存管理策略。它描述的问题是,如果你释放没有保留,或保留没有释放(或自动释放)。如果你们两个都这样做,我想这应该不是问题。 – morningstar

+0

唯一的相关行这里似乎是“NSException的所有实例都放置在主自动释放池。”我希望有一个指向Apple文档的指针说明了这一点,并且明确指出这与堆栈的关系如何从异常中解脱出来。 (例如,是它奇迹般地放在顶部自动释放池在它抓住了?或者它的抛出点,假设该池没有得到清理) –

+0

我敢肯定,这意味着当前autoreleasepool – hooleyhoop

1

@catch块做绝对没有生命周期。这里的隐式契约是一个NSException对象,即-raise'd或@thrown应该是一个自动释放对象。这意味着在@catch块中,您给出的NSException是一个自动释放对象,就像您可能从方法调用中获得的任何自动释放对象一样。您可以安全地将其存储在本地,并在@catch块之后引用它。

+0

这是如何发挥(如果有的话)嵌套autorelease池?我在抛出的地方得到了这个结果,你会抛出一个自动释放的对象,但是如果它最终通过多个嵌套的autorelease池被抛出呢?如果在最后的'@ finally'块中有'漏'字怎么办?这个潜在的问题只是被运行时忽略了,假设它运行良好?或者在运行时发生了一些特殊情况? –

+0

@quixoto:如果它获得通过自动释放池扔了,这些池会被丢弃在地上,不外流。但是,由于autorelease池的工作方式,一旦外池消耗,所有放在地板上的内池也会耗尽。不过是的,如果你在'@ finally'块里面有'漏',那么我不太清楚异常是如何表现的。系统在被抛出时可能会保留它,我不知道。 –

0

NSException采用NSCopying(和NSCoding fwiw)。如果您遇到可疑的生命周期并希望明确说明,那么复制将是理想的。

我停在那里 - 收放可可成语流动反目成仇。

2

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Exceptions/Tasks/HandlingExceptions.html

几乎所有NSException对象(和其他类型的异常对象的)被创建自动释放,这将它们分配到最近的(范围)自动释放池。当该池被释放时,异常被破坏。

而且,我敢肯定,某处memory programming guide,他们提到,如果没有newalloccopy方法,他们的名字总是按照惯例返回自动释放的对象。 NSException's methods符合资格。

轻微相关(未NSException但NSError):

如果创建一个NSError对象与initWithDomain:代码:USERINFO:,你应该送自动释放它,你就返回给调用者之前。

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html

+0

很好的参考。还有就是关于页面周围异常自动释放池的行为太多,这是粘性的情况下,我在很大程度上有兴趣的更详细的讨论。 –

+0

仍不能确定什么是“几乎所有”是指在那里。 – user123444555621

+0

也许它只是按照惯例。当然,'[NSException提高...'将被自动释放,但当然,你可以这样做:'ID富= [[美孚ALLOC] INIT]。 @throw FOO;' –

相关问题