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' 已被回收而打印出一些意想不到的东西。
在 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' 已被回收而打印出一些意想不到的东西。