Objective-C try-catch - 为什么编译成功?为什么 return 构建调试与发布不同?

Objective-C try-catch - why does this compile? And why is the return different building debug vs release?

在 Objective-C 类别中找到这段有趣的代码,用于捕获 NSExceptions 并将它们作为 NSErrors 传递给 Swift 代码。

我不明白的是: 1)为什么它甚至可以编译?如果抛出异常,则永远不会有 return 值。 2) 为什么在debug(优化级别none)和release(优化级别smallest/fastest)编译时return值不同?

- (BOOL)catchException:(void(^)())tryBlock error:(__autoreleasing NSError **)error {
   @try {
       tryBlock();
       return YES;
   }
   @catch (NSException *exception) {
       NSMutableDictionary *userInfo = [exception.userInfo mutableCopy];
       if (!userInfo) userInfo = [NSMutableDictionary new];
       userInfo[NSLocalizedDescriptionKey] = exception.reason;
       *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:userInfo];
   }
   // Note the missing return value outside the try-catch
 }

调用函数:

NSError *error;
BOOL result = [self catchException:^{
    @throw [NSException exceptionWithName:@"Exception" reason:@"WTF?" userInfo:nil];
} error:&error];

NSLog(@"Result: %@", result ? @"YES" : @"NO");

编译和运行调试方案时,我们得到:

2017-02-09 10:01:39.695 Compile Test[23129:630118] Result: NO

并且在对 Release 方案执行相同操作时:

2017-02-09 10:01:39.695 Compile Test[23129:630118] Result: YES

所以在这两种情况下似乎都有一个 return 值,即使在 try-catch 块之外没有 returned 值,并且 return 值在try-catch 从未达到。我们在这里都很困惑?!

这要么是编译器错误,要么是 "check control flow to make sure return value is present" 选项被关闭(如果有的话)。

不同的 return 值是因为行为未定义。

基本上,槽中发生的任何事情——可能是一个寄存器,可能在堆栈上,取决于目标 CPU 的 ABI —— 将 return 值保存在使用函数 returns 的时间。

如果不进行优化,编译器将不会重用寄存器和堆栈;每个变量都有自己的 space 并保存到函数的末尾。通过优化,编译器将主动重用内存,从而导致行为发生变化。这也是调试优化代码如此痛苦的原因; 'p myVariable' 可能仅仅因为 'myVariable' 已被回收而打印出一些意想不到的东西。