Swift EXC_BAD_INSTRUCTION(代码= EXC_i386_INVOP)

时间:2014-10-14 05:35:36

标签: iphone swift

我有这堂课:

class IdentifiableModel: KeyValueModel {
    class var OBJECT_ID: String { return "object_id" }

    override init() {
        super.init()
        self.setRandomId() // Breakpoint 1 HERE
    }
    override init(dict: Dictionary <String, String>) {
        super.init(dict: dict)
        self.setRandomId()
    }

    var objectId: String?

    func getObjectId() -> String? {
        return nil
    }

    func setObjectId(value: String) {

    }

    private func setRandomId() {
        if getObjectId() == nil { // Breakpoint 2 HERE
            setObjectId("\(Int(arc4random()))")
        }
    }
} 

实例化变量

 var obj = IdentifiableModel()

重现的步骤: 1)暂停断点1 2)继续断点2 3)多次踩踏。  在大多数情况下,程序将在断点2的行上显示EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP)

1 个答案:

答案 0 :(得分:3)

你的问题在于:

Int(arc4random())

arc4random()返回一个UInt32-a unsigned 32位整数。如果您编译32位平台的上述代码,比如iPhone 4,那么您尝试填充它的Swift Int将是一个32位签名的整数,一个Int32。 (这也是@Pavi无法在操场上重现问题的原因;操场将是64位。)

所以,在32位平台上,有时 - 大约一半的时间,实际上arc4random()将返回一个对你的Int构造函数来说太大的值,你就会得到一个库中的断言失败(EXC_BAD_INSTRUCTION是这个的正常线索;断言失败故意将错误的指令抛到处理器上以暂停一切。)

你基本上决定是否根据投掷硬币而崩溃:)

因此,您需要为您的ID使用特定的,足够大的整数类型(UInt32应始终有效,因为它是arc4_random的返回类型),或者限制随机数生成器的结果,例如,使用arc4random_uniform生成特定范围内的数字。

事实上,你可以通过删除不必要的强制转换来解决问题:

setObjectId("\(arc4random())")

......但当然,它取决于你实际上要做的事情,以及为什么......