1

我有以下课程:

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 应用程序中使用它来读取具有自定义格式的二进制文件。例如,要读取Int偏移量 5 处的值,我使用:

let foo = rawData.read(5) as Int

这可以在我的 iPad Air 模拟器上运行,并且已经通过了 beta 测试的审查。但是,我的外部测试人员有 iPad 2s 和 4s,他们遇到了EXC_ARM_DA_ALIGN错误。

我无法更改输入文件的结构。有什么方法可以修复该read功能以确保对象是从正确对齐的内存位置构建的?

4

2 回答 2

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 允许重载具有不同返回类型的函数,因此您实际上可以定义这两种方法,编译器会自动选择更严格的一个。

于 2015-02-13T20:09:42.383 回答
-2

致所有阅读本文的Swift开发人员

我有一个具有相同崩溃类型的不同案例!

如果您的项目是为(旧?)快速版本定义的,但是您链接到一个可可豆荚(在我的情况下),该可可豆荚在构建设置中具有不同的(较新?)快速版本-即使当您只是试图在常规swift struct中设置公共字段的值。

堆栈跟踪不会告诉您任何信息,并且可能会显示错误的位置(例如 CAAnimation 空闲内存)

就我而言,我的项目在Swift 4中,而我的 pod (SwiftMessages) 是Swift 4.2

繁荣

快乐编码!

于 2018-11-26T21:07:10.387 回答