如果在 catch 块中抛出异常,是不是会执行 finally 块? [复制]
Posted
技术标签:
【中文标题】如果在 catch 块中抛出异常,是不是会执行 finally 块? [复制]【英文标题】:Will a finally block be executed if exception thrown in catch block? [duplicate]如果在 catch 块中抛出异常,是否会执行 finally 块? [复制] 【发布时间】:2012-12-28 23:20:22 【问题描述】:可能重复:does code in finally get run after a return in objective-c?
考虑一下这个 Objective C 伪代码块:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@try
throw [[NSException alloc] init];
@catch (NSException *e)
throw e;
@finally
[pool drain];
游泳池会被排干吗?或者@catch
块中的throw
是否会使该代码无法访问?我觉得池应该被排干了,但我无法以某种方式找到有关它的文档。
是的,我可以编写一些代码并对其进行测试,但目前这是不可行的。
谢谢
【问题讨论】:
@Perception 可能的重复并不能回答这个问题。该问题和文档清楚地表明,无论 try 块中是否存在异常,都会调用 finally 子句,但没有提及如果从 catch 块中抛出异常会发生什么。它可能会被调用,但另一个问题并没有澄清这个问题。 @Madbreaks 从 Eugene 链接的文档看来,您应该调用“@throw”而不是“throw e”来重新抛出异常。文档有点暗示(尽管没有明确说明)如果你这样做,“最终”将被调用。 请注意,您绝对不应该为了从中恢复而捕获异常。在 ios 和 OS X 中,异常仅用于指示不可恢复的错误(极少数糟糕的奇怪情况)。 @DanJ 从什么时候开始我们在英文中的冒号后大写?请不要仅仅为了编辑而编辑,那不是编辑的目的。 @bbum 在这个 pseudocode 中你认为我试图从异常中恢复吗?相反,异常被重新提出。 【参考方案1】:Yes (docs)。
与本地@catch 异常处理程序关联的@finally 块 在@throw 导致下一个更高的异常处理程序之前执行 被调用。
在这种情况下,有关内存管理的进一步说明,请参阅链接文档页面的最底部。你在你的例子中是“好的”,因为异常本身并没有作为你在 finally 块中耗尽的池的一部分自动释放。但是如果没有人释放它,您可能会泄漏该异常。
(但在某些情况下,异常生命周期似乎有些模糊,请参阅:What is the lifecycle of an object caught in a @catch block?)
【讨论】:
谢谢 - 这是我见过的最令人放心的文档(显然我还没有看到全部)。我觉得其他地方的文档只讨论try
块中提出的异常,这就是为什么我很难简单地接受事实。
@Eugene 发布的示例程序似乎与此不矛盾吗?
@Madbreaks 否——在记录器有机会打印到控制台之前,他的示例应用程序会因未处理的异常而死掉。如果您使用相同的示例,但在另一个 try/catch 中调用它,您将看到打印出的“finally”日志。【参考方案2】:
来自https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Exceptions/Tasks/HandlingExceptions.html:
@finally — Defines a block of related code that is subsequently executed whether an exception is thrown or not.
但它没有说明 catch 块中的异常。 听起来很合乎逻辑,这个例外不会被咳出来。
我已经制作了简单的程序来检查:
import <Foundation/Foundation.h>
int main(int argc, char **argv)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] ;
int result = 0 ;
@try
@throw [NSException exceptionWithName:@"Exception" reason:@"@try" userInfo:nil];
@catch (id exception)
@throw [NSException exceptionWithName:@"Exception" reason:@"@catch" userInfo:nil];
@finally
NSLog(@"Finally");
[pool release] ;
return result ;
只需编译并执行:
$ gcc -framework Foundation -fobjc-exceptions test.m
$ ./a.out
2012-12-29 00:39:21.667 a.out[86205:707] *** Terminating app due to uncaught exception 'Exception', reason: '@catch'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8e3050a6 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8e56e3f0 objc_exception_throw + 43
2 a.out 0x0000000107d48d47 main + 359
3 libdyld.dylib 0x00007fff90b4e7e1 start + 0
)
libc++abi.dylib: terminate called throwing an exception
Abort trap: 6
【讨论】:
看,但是,我不相信这就是报价所说的。我相信这句话是说finally
块将被执行,无论try
块中是否引发异常。对我来说,根据那句话接受它是一个灰色地带。
@BenZotto 我已经更正了答案。丢失了原始问题中关于 catch 块的部分
“这个异常不会被咳出来听起来合乎逻辑”,对,它不会。这不是我要问的。我在问(在您的示例中)"Finally"
是否会被记录。以上是关于如果在 catch 块中抛出异常,是不是会执行 finally 块? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
JAVA语言如何进行异常处理,关键字throws,throw,try,catch,finally分别代表啥意义在try块中抛出异常吗