如果在 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 块? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP Try Catch 块中抛出异常

在 try 块中抛出异常后,catch 块不会立即执行

在PHP Try Catch块中抛出异常

JAVA语言如何进行异常处理,关键字throws,throw,try,catch,finally分别代表啥意义在try块中抛出异常吗

在 finally 块中抛出异常

finally中流关闭失败需要抛出异常吗