ios - 在 Swift 中从 NSData 读取时的 EXC_ARM_DA_ALIGN

标签 ios swift unsafe-pointers

我有以下类(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
}

这适用于所有整数和浮点类型。

对于一般情况,可以使用 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 允许重载具有不同返回类型的函数, 因此你实际上可以定义两个方法,编译器会 自动选择限制性更强的一个。

关于ios - 在 Swift 中从 NSData 读取时的 EXC_ARM_DA_ALIGN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28507412/

相关文章:

ios - 在 Swift 中将自定义输入 View 添加到 UITextField

iphone - 检查字符串是否有空格

ios - 如何在 Swift 5 中将文档转换为自定义对象?

swift - 如何从现有 CGRect 创建 UnsafePointer<CGRect>

ios - 导航栏按钮和项目未在 swift 3 中显示

objective-c - 接收带有特殊字符的 XML

ios - 退出程序(后台进入)后是否可以保持变量?

ios - 点亮一个 UIColor

swift - 在 Swift 3 (libxml2) 中将 String 转换为 UnsafePointer<xmlChar> 的更快捷方式

swift - CGPathAddArc 在创建路径时遇到一些问题