Shaun Inman Shaun Inman - 2 months ago 12
Swift Question

Crash when casting the result of arc4random() to Int

I've written a simple Bag class. A Bag is filled with a fixed ratio of Temperature enums. It allows you to grab one at random and automatically refills itself when empty. It looks like this:

class Bag {
var items = Temperature[]()

init () {
refill()
}

func grab()-> Temperature {
if items.isEmpty {
refill()
}

var i = Int(arc4random()) % items.count
return items.removeAtIndex(i)
}

func refill() {
items.append(.Normal)

items.append(.Hot)
items.append(.Hot)

items.append(.Cold)
items.append(.Cold)
}
}


The Temperature enum looks like this:

enum Temperature: Int {
case Normal, Hot, Cold
}


My
GameScene:SKScene
has a constant instance property
bag:Bag
. (I've tried with a variable as well.) When I need a new temperature I call
bag.grab()
, once in
didMoveToView
and when appropriate in
touchesEnded
.

Randomly this call crashes on the
if items.isEmpty
line in
Bag.grab()
. The error is
EXC_BAD_INSTRUCTION
. Checking the debugger shows items is
size=1
and
[0] = (AppName.Temperature) <invalid> (0x10)
.

Edit Looks like I don't understand the debugger info. Even valid arrays show
size=1
and unrelated values for
[0] =
. So no help there.

I can't get it to crash isolated in a Playground. It's probably something obvious but I'm stumped.

Answer

Function arc4random returns an UInt32. If you get a value higher than Int.max, the Int(...) cast will crash.

Using

Int(arc4random_uniform(UInt32(items.count)))

should be a better solution.

(Blame the strange crash messages in the Alpha version...)

Comments