我在运行看起来非常安全的快速代码时遇到了一个奇怪的Bus Error
。我试图将其减少到最小的测试用例,如下所示:
Apple Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift 0ddf238ad7)
Target: x86_64-apple-macosx10.9
此代码:
public enum MyError: ErrorType {
case SomeError(code: Int)
}
public typealias MyType = () throws -> Bool
public class Foo {
var a:MyType = { () throws -> Bool in
print("A")
return true
}
var b:MyType = { () throws -> Bool in
print("B")
return true
}
var c:MyType = { () throws -> Bool in
print("C")
throw MyError.SomeError(0)
}
}
public func handle<T>(test:T) {
let mirror = Mirror(reflecting: test)
print(mirror.subjectType)
for child in mirror.children {
if let callable = child.value as? MyType {
do {
try callable()
}
catch MyError.SomeError(let id) {
print(id)
}
catch {
print("unknown error")
}
}
}
}
let foo = Foo()
handle(foo)
生成此输出:
Foo
A
B
C
Bus error: 10
在调试器中运行它可以正常工作,所以我认为它与运行时的时序问题有关。
我在这段代码中做了非法或不安全的事情吗?
在闭包中异常是不合法的吗?
造成此错误的原因是什么?
编辑:
我已经在此处创建了一个关于swift问题跟踪器的错误:https://bugs.swift.org/browse/SR-324
答案 0 :(得分:4)
造成此错误的原因是什么?
在你到达最后一次关闭之前,错误不会发生:
var c:MyType = { () throws -> Bool in
print("C")
throw MyError.SomeError(0)
}
显然,你在这里抛出一个异常,我怀疑这个问题与迭代children
的关系不大,更多的是在你执行此操作时抛出异常迭代。我试着在没有迭代的情况下调用c
:
public func trythis() {
let foo = Foo()
do {
try (foo.c)()
}
catch MyError.SomeError(let id) {
print(id)
}
catch { print("unknown") }
}
trythis()
发现它工作正常。我还尝试从throw
中删除c
:
var c:MyType = { () throws -> Bool in
print("C")
// throw MyError.SomeError(code: 0)
return true
}
并发现代码在这种情况下工作正常。因此,在迭代问题列表时抛出组合,这让我怀疑它只是编译器错误或者Mirror
类可能有问题
我认为您应该向Apple提交此错误报告。
答案 1 :(得分:2)
我同意Caleb的说法,这一定是个错误。
但是要明确一点,它不是在迭代时抛出的组合。它是反映和投掷的组合。
这是handle
功能的修改版本:
public func handle<T>(test:T) {
let mirror = Mirror(reflecting: test)
print(mirror.subjectType)
// Extract only the last function, no iteration...
if let callable = mirror.children[AnyForwardIndex(2)].value as? MyType {
do {
try callable()
}
catch MyError.SomeError(let id) {
print(id)
}
catch {
print("unknown error")
}
}
}
此功能将导致与您的功能相同的错误。 如果使用反射找到,你根本无法调用抛出的函数。
我会说错误。