Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
189 views
in Technique[技术] by (71.8m points)

iphone - Swift EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP)

I have this class:

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()))")
        }
    }
} 

Instantiate a variable

 var obj = IdentifiableModel()

Steps to reproduce: 1) Pause on breakpoint 1 2) Continue to breakpoint 2 3) Step over multiple times. In most of the cases the program will show EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP) on the line with Breakpoint 2.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your problem lies here:

Int(arc4random())

arc4random() returns a UInt32—an unsigned 32-bit integer. If you compile the above code for a 32-bit platform, like an iPhone 4, say, then the Swift Int you're trying to stuff it into will be a 32-bit signed integer, an Int32. (This is also the reason @Pavi can't reproduce the problem in a playground; the playground will be 64-bit.)

So, on a 32-bit platform, sometimes—about half the time, in fact—arc4random() will be returning a value that's too large for your Int constructor, and you'll get an assertion failure in the library (EXC_BAD_INSTRUCTION is the normal clue to this; assertion failures deliberately throw a bad instruction onto the processor to halt everything.)

You're basically deciding whether to crash based on the toss of a coin :)

So, you either need to use a specific, large enough integer type for your ID (UInt32 should always work, as that's the return type of arc4_random), or limit the results of the random number generator, for example by using arc4random_uniform to generate numbers within a specific range.

In fact, you could probably fix things by removing the unnecessary cast to an integer anyway:

setObjectId("(arc4random())")

...but of course it'll depend on what you're actually trying to do, and why...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...