从Swift中的NSData读取时的EXC_ARM_DA_ALIGN

时间:2015-02-13 19:37:16

标签: ios swift unsafe-pointers

我有以下课程:

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函数以确保对象是从正确对齐的内存位置构建的?

2 个答案:

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

编码愉快!