Swift 范围内的快速变异数据
我正在构建一个Swift 范围内的快速变异数据,swift,nsdata,unsafe-pointers,Swift,Nsdata,Unsafe Pointers,我正在构建一个数据对象,其外观如下: struct StructuredData { var crc: UInt16 var someData: UInt32 var someMoreData: UInt64 // etc. } aMethod(¶m) 我正在运行一个CRC算法,它将从字节2开始,进程长度为12 返回CRC时,它必须存在于数据对象的开头。在我看来,我的选择是: 生成一个不包含CRC的数据对象,对其进行处理,然后构建另一个包含CRC的数据对象(这
数据
对象,其外观如下:
struct StructuredData {
var crc: UInt16
var someData: UInt32
var someMoreData: UInt64
// etc.
}
aMethod(¶m)
我正在运行一个CRC算法,它将从字节2开始,进程长度为12
返回CRC时,它必须存在于数据
对象的开头。在我看来,我的选择是:
数据
对象,对其进行处理,然后构建另一个包含CRC的数据
对象(这样我现在拥有的CRC值将位于数据
对象的开头)[0..我找到了它。实际上,我遇到了一个语法错误,这让我感到难以置信,因为我以前没有看到过
答案如下:
data.replaceSubrange(0..<2, with: UnsafeBufferPointer(start: &self.crc, count: 1))
data.replaceSubrange(0..我找到了答案。我实际上遇到了一个语法错误,这让我感到难以置信,因为我以前从未见过这个错误
答案如下:
data.replaceSubrange(0..<2, with: UnsafeBufferPointer(start: &self.crc, count: 1))
data.replaceSubrange(0..
data.replaceSubrange(0..<2, with: UnsafeBufferPointer(start: &self.crc, count: 1))
- Swift分配一些大小足以容纳
param
内容的区域
- 将
param
复制到区域中,(复制到)
- 通过传递区域的地址调用方法
- 从调用返回时,将区域内容复制回
param
(复制)
在许多情况下,Swift仅通过传递param
的实际地址来优化步骤(即使在-Onone
设置中也可能发生),但没有明确的文档记录
因此,当inout
参数传递给UnsafeBufferPointer
的初始值设定项时,UnsafeBufferPointer
接收的地址可能指向一个临时区域,该临时区域将在初始值设定项完成后立即释放
因此,replaceSubrange(u:with:)
可以将已发布区域中的字节复制到数据中
我相信第一个代码在这种情况下会起作用,因为crc
是结构的一个属性,但是如果有一个简单而安全的替代方法,您最好避免使用不安全的方法
补充布兰登·曼泽伊自己的回答
data.append(UnsafeBufferPointer(start: &self.crcOfRecordData, count: 1))
按照上述含义使用safe。出于上述相同原因,这是不安全的
我会这样写:
data.append(Data(bytes: &self.crcOfRecordData, count: MemoryLayout<UInt16>.size))
withUnsafeBytes(of: &self.crcOfRecordData) {urbp in
data.append(urbp.baseAddress!.assumingMemoryBound(to: UInt8.self), count: MemoryLayout<UInt16>.size)
}
let uint32Data = Data(bytes: &self.someData, count: MemoryLayout<UInt32>.size)
注释中未提及这一点,但根据上述安全的含义,以下行不安全
同样的原因
我会这样写:
data.append(Data(bytes: &self.crcOfRecordData, count: MemoryLayout<UInt16>.size))
withUnsafeBytes(of: &self.crcOfRecordData) {urbp in
data.append(urbp.baseAddress!.assumingMemoryBound(to: UInt8.self), count: MemoryLayout<UInt16>.size)
}
let uint32Data = Data(bytes: &self.someData, count: MemoryLayout<UInt32>.size)
让uint32Data=Data(字节:&self.someData,计数:MemoryLayout.size)
尽管如此,可观察到的意外行为可能会在一些非常有限的条件下发生,并且概率非常小
只有满足以下两个条件时,才会发生这种行为:
Swift编译器生成非优化的复制入复制出代码
在非常窄的时间段之间,由于时间区域被释放,直到append
方法(或Data.init
)完成对整个内容的复制,因此该区域被修改以供其他用途
条件#1仅在当前实施Swift的有限情况下变为真
只有在多线程环境中才会出现条件#2(尽管如此,苹果的框架使用了许多隐藏线程,正如你可以在Xcode的调试器中找到的那样)
事实上,我没有看到任何关于上述不安全案例的问题,我的保险箱可能有点过分了
但其他安全代码并没有那么复杂,是吗?
在我看来,您最好习惯于使用所有情况下的安全代码。我不建议使用以下方法对数据进行变异:
data.replaceSubrange(0..<2, with: UnsafeBufferPointer(start: &self.crc, count: 1))
- Swift分配一些大小足以容纳
param
内容的区域
- 将
param
复制到区域中,(复制到)
- 通过传递区域的地址调用方法
- 从调用返回时,将区域内容复制回
param
(复制)
在许多情况下,Swift仅通过传递param
的实际地址来优化步骤(即使在-Onone
设置中也可能发生),但没有明确的文档记录
因此,当inout
参数传递给UnsafeBufferPointer
的初始值设定项时,UnsafeBufferPointer
接收的地址可能指向一个临时区域,该临时区域将在初始值设定项完成后立即释放
因此,replaceSubrange(u:with:)
可以将已发布区域中的字节复制到数据中
我相信第一个代码在这种情况下会起作用,因为crc
是结构的一个属性,但是如果有一个简单而安全的替代方法,您最好避免使用不安全的方法
补充布兰登·曼泽伊自己的回答
data.append(UnsafeBufferPointer(start: &self.crcOfRecordData, count: 1))
按照上述含义使用safe。出于上述相同原因,这是不安全的
我会这样写:
data.append(Data(bytes: &self.crcOfRecordData, count: MemoryLayout<UInt16>.size))
withUnsafeBytes(of: &self.crcOfRecordData) {urbp in
data.append(urbp.baseAddress!.assumingMemoryBound(to: UInt8.self), count: MemoryLayout<UInt16>.size)
}
let uint32Data = Data(bytes: &self.someData, count: MemoryLayout<UInt32>.size)
注释中未提及这一点,但根据上述安全的含义,以下行不安全
同样的原因
我会这样写:
data.append(Data(bytes: &self.crcOfRecordData, count: MemoryLayout<UInt16>.size))
withUnsafeBytes(of: &self.crcOfRecordData) {urbp in
data.append(urbp.baseAddress!.assumingMemoryBound(to: UInt8.self), count: MemoryLayout<UInt16>.size)
}
let uint32Data = Data(bytes: &self.someData, count: MemoryLayout<UInt32>.size)
让uint32Data=Data(字节:&self.someData,计数:MemoryLayout.size)
尽管如此,可观察到的意外行为可能会在一些非常有限的条件下发生,并且概率非常小
只有满足以下两个条件时,才会发生这种行为:
Swift编译器生成非优化的复制入复制出代码
在非常窄的时间段之间,由于时间区域被释放,直到append
方法(或Data.init
)完成对整个内容的复制,因此该区域被修改以供其他用途
条件#1仅为真