Swift 4.1 runtime error with Data range

This code:


let d0 = Data(bytes: [10, 11, 12, 13, 14, 15])
print(d0[2])
print(d0[3])
let d1 = d0[2...3]
print(d1.count)
print(d1[0])


...produces this output in an Xcode 9.3 / Swift 4.1 playground:


12
13
2


...and then crashes on the last line:


print(d1[0])


...with this error:


error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).


Is this a bug, and if so, any suggestions for a workaround?

Accepted Reply

if you test :


print(d1[2], d1[3])


you get

12 13

So, that shows that indexes still refer to the original array.

It is normal behavior for slices, as documented here :

h ttps://developer.apple.com/documentation/swift/arrayslice


Unlike

Array
and
ContiguousArray
, the starting index for an
ArraySlice
instance isn’t always zero. Slices maintain the same indices of the larger array for the same elements, so the starting index of a slice depends on how it was created, letting you perform index-based operations on either a full array or a slice.

Replies

if you test :


print(d1[2], d1[3])


you get

12 13

So, that shows that indexes still refer to the original array.

It is normal behavior for slices, as documented here :

h ttps://developer.apple.com/documentation/swift/arrayslice


Unlike

Array
and
ContiguousArray
, the starting index for an
ArraySlice
instance isn’t always zero. Slices maintain the same indices of the larger array for the same elements, so the starting index of a slice depends on how it was created, letting you perform index-based operations on either a full array or a slice.

Thanks, that makes sense. But I think the code was working in Swift 4.0 for some reason. Perhaps it shouldn't have been, and now 4.1 fixes this. In my actual implemtation, I pass the range to a function that accepts a Data argument like so:

func f(_ data: Data) {
  print(data.startIndex)
}
let d0 = Data(bytes: [10, 11, 12, 13, 14, 15])
let d1 = d0[4...5]
f(d1)
f(Data(d1))

Inside function "f" I access the data, and this is where the index behavior has changed, if I'm not mistaken. The playground output from the above is now:

4
0

I don't think it worked in 4.0.


I have tried with Swift 3:

let d0 = [10, 11, 12, 13, 14, 15]
let d1 = d0[2...3]
print(d1.count)
print(d1[0])


And got the same error (I had to change a bit, as Data does not work in Swift3, but the message is about slice) ; in addition, documentation is cystal clear on the point.


You ask to print startInex, hence you get 4 for d1, that's logical

I think, when you call f(Data(d1)), you just create a new Data, hence startIndex becomes 0


Why do you need to use data and not plain arrays ?

The reason I use Data and not an array is because the actual application where this crash started occurring in Swift 4.1 uses Data for reasons outside the scope of this post. I posted a distilled version of the code here just to illustrate the issue I'm experiencing. Thanks again for your help and insights.