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!!!

编码愉快!