2012-12-28 47 views
3

可能重复:
does code in finally get run after a return in objective-c?如果在catch块中抛出异常,是否会执行finally块?

考虑目标C伪代码的此块:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

@try { 
    throw [[NSException alloc] init]; 
} 
@catch (NSException *e) { 
    throw e; 
} 
@finally { 
    [pool drain]; 
} 

将池倒掉?或者@catch块中的throw呈现该代码无法访问?我觉得池应该被耗尽,但我无法以这种或那种方式找到它的文档。

是的,我可以写一些代码并测试它,但目前不可行。

感谢

+2

@Perception这可能重复不回答这个问题。该问题和文档清楚地表明finally子句在try块中是否存在异常,但没有提及如果从catch块抛出异常会发生什么。它可能被称为,但另一个问题并没有澄清这个问题。 – rmaddy

+0

@Madbreaks从Eugene链接的文档看来,您应该调用“@throw”而不是“throw e”来重新抛出异常。如果你这样做的话,这个文档暗示(尽管没有明确说明)“终于”会被调用。 – rmaddy

+0

请注意,您绝对不应该为了从中恢复而捕获异常。在iOS和OS X中,异常仅用于指示不可恢复的错误(只有极少数可怜的奇数情况)。 – bbum

回答

4

Yes (docs)

与本地@catch异常处理程序 相关联的@finally块@throw导​​致下一个较高的异常处理程序 要被调用之前执行。

有关内存管理的进一步说明,请参阅链接文档页面的底部。在你的例子中你是“OK”,因为这个异常本身并不是自动释放的,因为你的finally块中正在耗尽的池的一部分。但是如果没有人释放它,你可能会泄露该异常。

(但似乎有大约在某些情况下例外生命周期的某些不确定性,请参阅:What is the lifecycle of an object caught in a @catch block?

+0

谢谢 - 这是我见过的最令人放心的文档(显然我没有看到这一切)。我觉得其他地方的文档只讨论'try'块中提出的异常,这就是为什么我很难接受真相。 – Madbreaks

+0

@Eugene发布的示例程序是否与此相矛盾? – Madbreaks

+1

@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 
+0

看到,但我不相信这是报价说的。我相信这句话是说''finally'块会被执行,无论'try'块中是否抛出异常。接受它作为基于这句话的真相对我来说是一个灰色地带。 – Madbreaks

+0

@BenZotto我已经纠正了答案。在原始问题中丢失了关于catch block的部分 – Ievgen

+0

_“听起来合乎逻辑的是,这个异常不会发生”,对,它不会。这不是我要问的。我问是否(在你的例子中)'“Finally”将被记录或不记录。 – Madbreaks

相关问题