Swift UnsafePointer<T>(data.bytes).memory crash under some (but not all) 情况下
Swift UnsafePointer<T>(data.bytes).memory crash under some (but not all) circumstances
我有以下结构:
struct Identity {
var id: Int
var createdAt: NSDate
var string: String
var apnsToken: String
}
在我的应用程序执行过程中,此结构的实例 (?) 被转换为 NSData
(使用以下代码)并存储在 NSUserDefaults
:
var id = Identity(id: 0, createdAt: NSDate(), string: "string", apnsToken: "<apns-token-here>")
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
当我尝试从 NSData
实例获取结构时,它崩溃并显示 EXC_BAD_ACCESS(它是代码 1):
var id = UnsafePointer<Identity>(userDefaultsData.bytes).memory
但是,只有当我从 NSUserDefaults 获取 NSData
实例时才会发生这种情况。如果我像下面那样做,它就不会崩溃。
var id = Identity(id: 0, createdAt: NSDate(), string: "string", apnsToken: "<apns-token-here>")
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
var idPrime = UnsafePointer<Identity>(data.bytes).memory
EXC_BAD_ACCESS 转储的汇编代码在 objc_retain 中途的某处,在 and
指令之后。
更新:
我并不完全诚实。从 ObjC 中的钥匙串中检索数据,bridge_transfer 从 CF 数据对象转换为 NSData
。 CF 对象作为输出参数来自 SecItemCopy()
。我认为 NSUserDefaults
会更贴切。
这是因为这一行:
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
将不会将String
s(或分配自己内存的任何其他类型,如数组)呈现为字节形式。相反,它所做的只是将指向字符串内存的 指针 序列化为 NSData
字节。
如果内存不再存在,这显然会导致爆炸。这就是为什么当您一次完成所有操作时它似乎可以正常工作,但当您存储到用户默认值然后稍后甚至可能在不同的过程中将其取回时却无法正常工作。
相反,你需要做一些事情,比如将字符串存储到它们自己的 NSData
对象中(比如 NSData(base64EncodedString:options:)
),然后也存储它。
我有以下结构:
struct Identity {
var id: Int
var createdAt: NSDate
var string: String
var apnsToken: String
}
在我的应用程序执行过程中,此结构的实例 (?) 被转换为 NSData
(使用以下代码)并存储在 NSUserDefaults
:
var id = Identity(id: 0, createdAt: NSDate(), string: "string", apnsToken: "<apns-token-here>")
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
当我尝试从 NSData
实例获取结构时,它崩溃并显示 EXC_BAD_ACCESS(它是代码 1):
var id = UnsafePointer<Identity>(userDefaultsData.bytes).memory
但是,只有当我从 NSUserDefaults 获取 NSData
实例时才会发生这种情况。如果我像下面那样做,它就不会崩溃。
var id = Identity(id: 0, createdAt: NSDate(), string: "string", apnsToken: "<apns-token-here>")
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
var idPrime = UnsafePointer<Identity>(data.bytes).memory
EXC_BAD_ACCESS 转储的汇编代码在 objc_retain 中途的某处,在 and
指令之后。
更新:
我并不完全诚实。从 ObjC 中的钥匙串中检索数据,bridge_transfer 从 CF 数据对象转换为 NSData
。 CF 对象作为输出参数来自 SecItemCopy()
。我认为 NSUserDefaults
会更贴切。
这是因为这一行:
var data = NSData(bytesNoCopy: &id, length: sizeof(Identity),freeWhenDone:false)
将不会将String
s(或分配自己内存的任何其他类型,如数组)呈现为字节形式。相反,它所做的只是将指向字符串内存的 指针 序列化为 NSData
字节。
如果内存不再存在,这显然会导致爆炸。这就是为什么当您一次完成所有操作时它似乎可以正常工作,但当您存储到用户默认值然后稍后甚至可能在不同的过程中将其取回时却无法正常工作。
相反,你需要做一些事情,比如将字符串存储到它们自己的 NSData
对象中(比如 NSData(base64EncodedString:options:)
),然后也存储它。