EXC_ARM_DA_ALIGN 从 Swift 中的 NSData 读取时
EXC_ARM_DA_ALIGN when reading from NSData in Swift
我有以下 class:
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
函数以确保对象是从正确对齐的内存位置构建的?
是的,读取未对齐的数据在某些架构上可能会失败。
一种安全的方法是 将字节复制 到一个(正确对齐的)变量中。
所以第一个想法是编写一个通用函数:
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
}
这适用于所有整数和浮点类型。
对于一般情况,可以使用 :
中的想法
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 允许重载具有不同 return 类型的函数,
因此你实际上可以定义 both 方法,编译器会
自动选择限制性更强的那个。
FOR ALL SWIFT DEVELOPERS THAT READ THIS
我遇到了具有相同崩溃类型的不同案例!
如果您的项目是为(旧的?)swift 版本定义的,但是您 link 针对具有不同(较新的?)的 cocoa pod(在我的例子中) build settings 中的 swift 版本 - 即使您只是尝试设置 崩溃 的值,您也会遇到 崩溃 =36=] 常规 swift 结构中的字段 .
堆栈跟踪不会告诉您任何信息,并且可能会向您显示错误的位置(例如 CAAnimation 可用内存)
在我的例子中,我的项目在 Swift 4,我的广告连播 (SwiftMessages) 在 Swift4.2
AND BOOM!!!
编码愉快!
我有以下 class:
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
函数以确保对象是从正确对齐的内存位置构建的?
是的,读取未对齐的数据在某些架构上可能会失败。 一种安全的方法是 将字节复制 到一个(正确对齐的)变量中。
所以第一个想法是编写一个通用函数:
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
}
这适用于所有整数和浮点类型。
对于一般情况,可以使用 :
中的想法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 允许重载具有不同 return 类型的函数, 因此你实际上可以定义 both 方法,编译器会 自动选择限制性更强的那个。
FOR ALL SWIFT DEVELOPERS THAT READ THIS
我遇到了具有相同崩溃类型的不同案例!
如果您的项目是为(旧的?)swift 版本定义的,但是您 link 针对具有不同(较新的?)的 cocoa pod(在我的例子中) build settings 中的 swift 版本 - 即使您只是尝试设置 崩溃 的值,您也会遇到 崩溃 =36=] 常规 swift 结构中的字段 .
堆栈跟踪不会告诉您任何信息,并且可能会向您显示错误的位置(例如 CAAnimation 可用内存)
在我的例子中,我的项目在 Swift 4,我的广告连播 (SwiftMessages) 在 Swift4.2
AND BOOM!!!
编码愉快!