我有以下课程:
class RawDataArray {
var data: NSData!
init(filePath: String) {
data = NSData(contentsOfFile: filePath)
}
func read<T>(offset: Int) -> T {
return UnsafePointer<T>(data.bytes + offset).memory
}
}
我在我的iOS应用程序中使用自定义格式的二进制文件进行读取。例如,要在偏移5处读取Int
,我使用:
let foo = rawData.read(5) as Int
这可以在模拟器上,在我的iPad Air上运行,并且已经通过了beta测试的审核。但是,我的外部测试人员有iPad 2s和4s,他们收到EXC_ARM_DA_ALIGN
错误。
我无法更改输入文件的结构。有没有办法修复read
函数以确保对象是从正确对齐的内存位置构建的?
答案 0 :(得分:2)
是的,读取未对齐的数据可能会在某些体系结构上失败。 一种安全的方法是将字节复制到(正确对齐的)变量中。
所以第一个想法是写一个通用函数:
func read<T>(offset: Int) -> T {
var value : T
memcpy(&value, data.bytes + offset, UInt(sizeof(T)))
return value
}
但是,这不会编译,因为变量value
必须在使用前初始化,并且没有默认值
可用于初始化完整泛型的构造函数
变量
如果我们将方法限制为可以使用0
初始化的类型,那么我们得到这个:
func read<T : IntegerLiteralConvertible>(offset: Int) -> T {
var value : T = 0
memcpy(&value, data.bytes + offset, UInt(sizeof(T)))
return value
}
这适用于所有整数和浮点类型。
对于一般情况,可以使用https://stackoverflow.com/a/24335355/1187415中的想法:
func read<T>(offset: Int) -> T {
// Allocate space:
let ptr = UnsafeMutablePointer<T>.alloc(1)
// Copy data:
memcpy(ptr, data.bytes + offset, UInt(sizeof(T)))
// Retrieve the value as a new variable:
var item = ptr.move()
// Free the allocated space
ptr.dealloc(1)
return item
}
Swift允许重载具有不同返回类型的函数, 因此,你可以实际定义两个方法,编译器将 自动选择限制性更强的。
答案 1 :(得分:-1)
所有阅读此内容的 SWIFT 开发者
我有一个不同的案例,并且崩溃类型相同!
如果您的项目是为(旧?)快速版本定义的,但您链接到在构建设置中具有不同(较新?)快速版本的可可豆荚(以我为例)-即使您只是尝试在常规的 swift结构中设置公共字段的值,也将导致崩溃。
堆栈跟踪不会告诉您任何信息,并且可能会向您显示错误的位置(例如,CAAnimation的可用内存)
在我的情况下,我的项目在 Swift 4 中,而我的pod(SwiftMessages)是 Swift 4.2
并且 BOOM !!!
编码愉快!