这个小Swift片段在最后一次赋值时崩溃Xcode 9.2游戏,虽然缓冲区仍然保存23个字节。任何想法为什么会这样?
import Cocoa
var str = "01234567890123456789012345678901234567"
var buffer = Data()
if let data = str.data(using: .utf8) {
buffer.append(data)
buffer = buffer[15..<38]
buffer = buffer[2..<23]
}
看起来这是由SDK错误或编译器优化引起的,两者都试图避免不必要的数据副本(也就是写时复制)。在有问题的行上设置断点并检查buffer
会显示如下:
因此缓冲区指向相同的数据存储,但是不同的切片,并且尝试在切片外部访问会导致崩溃。
将有问题的行更改为buffer = buffer[17..<38]
会导致崩溃消失。
我不知道为什么按范围下标导致Data
可能导致崩溃,如果在代码的另一个(可能不相关的)部分中使用,而不知道它们正在处理切片。其他集合,如Array
有专用的切片类型,您可以期望它们具有各种有效的索引。
这是一个支持上述想法的天真例子:
func printFirstByte(of data: Data) {
print(data[0])
}
let str = "01234567890123456789012345678901234567"
if let data = str.data(using: .utf8) {
printFirstByte(of: data[15..<38]) // this call crashes
}
另一方面,我们确实在startIndex类型上有endIndex和Data
属性,但是这使得使用Data
实例变得更加困难,因为我们需要在将Data
切片发送到旧之前将其置零。不知道此行为的代码。