gpt4 book ai didi

swift - UnsafeMutableRawPointer 到 UnsafeMutablePointer : EXC_BAD_ACCESS on pointee

转载 作者:搜寻专家 更新时间:2023-11-01 05:33:54 24 4
gpt4 key购买 nike

我正在尝试从使用 Unmanaged.passUnretained().toOpaque() 获得的 UnsafeMutableRawPointer 获取 UnsafeMutablePointer:

class C { var foo = 42, bar = "bar" }
let c = C()

let rawPointer = Unmanaged.passUnretained(c).toOpaque()

let pointer = rawPointer.bindMemory(to: C.self, capacity: 1)
let pointee = pointer.pointee
print(pointee.foo) // EXC_BAD_ACCESS

这是一些 LLDB 输出,这对我来说看起来很奇怪,因为在我请求它的 pointee 之前,pointer 中的一切似乎都很好:

(lldb) frame variable -L c
scalar: (memtest2.C) c = 0x0000000101d00030 {
0x0000000101d00040: foo = 42
0x0000000101d00048: bar = "bar"
}
(lldb) frame variable -L rawPointer
0x00000001005e2e08: (UnsafeMutableRawPointer) rawPointer = {
scalar: _rawValue = 0x0000000101d00030 {
0x0000000101d00040: foo = 42
0x0000000101d00048: bar = "bar"
}
}
(lldb) frame variable -L pointer
0x00000001005e2e10: (UnsafeMutablePointer<memtest2.C>) pointer = 0x0000000101d00030
(lldb) frame variable -L pointer._rawValue
scalar: (memtest2.C) pointer._rawValue = 0x0000000101d00030 {
0x0000000101d00040: foo = 42
0x0000000101d00048: bar = "bar"
}
(lldb) frame variable -L pointee
0x00000001005e2e18: (memtest2.C) pointee = 0x00000001005b65d8 {
0x00000001005b65e8: foo = 140736790071664
0x00000001005b65f0: bar = ""
}

我还尝试了assumingMemoryBound(to:)load(as:),或者简单地:

let pointer = UnsafePointer<C>(bitPattern: Int(bitPattern: rawPointer))!
print(pointer.pointee.foo) // EXC_BAD_ACCESS

但我总是收到此 EXC_BAD_ACCESS 错误。这是怎么回事?

最佳答案

我的rawPointer 指向c 实例数据所在的位置。正如我所料,它不是引用的指针。类是引用类型:c的值是类实例数据所在的内存地址。然而 toOpaque() 文档很清楚:

Unsafely converts an unmanaged class reference to a pointer.

(toOpaque() 实际上调用了 unsafeBitCast(c, UnsafeMutableRawPointer.self))

要在引用上有一个指针,可以简单地做:

let referencePointer = UnsafeMutablePointer<C>(&c)

由于我的 rawPointer 指向实例数据,执行 pointer.pointee 告诉运行时实例数据的第一个单词是(或其)引用。这当然是不正确的,也没有道理。

说明:(我稍微改变了我的初始代码:foobar 都是 Int)

(lldb) frame variable c
(testmem.C) c = 0x0000000101833580 (foo = 42, bar = 84)

这 (0x0000000101833580) 是实例数据所在的位置。让我们看看这个地址的内存包含什么:

(lldb) memory read 0x0000000101833580
0x101833580: e0 65 5b 00 01 00 00 00 02 00 00 00 00 00 00 00
0x101833590: 2a 00 00 00 00 00 00 00 54 00 00 00 00 00 00 00

我了解到第一个词 (e0 65 5b 00 01 00 00 00) 是类型数据,第二个 (02 00 00 00 00 00 00 00) 是引用计数(这个我不太了解),剩下的就是实例数据了。事实上,0x2a 是 42,0x54 是 84。foobar 的值。

执行 pointer.pointee 意味着告诉运行时第一个单词(e0 65 5b 00 01 00 00 000x00000001005b65e0)是一个指向我们的实例数据所在位置的引用(显然不是这样)!暗示 pointer.pointee.foo 位于 0x00000001005b65e0 + 16 (0x00000001005b65f0) 和 bar + 24 ( 0x00000001005b65f0)。

(lldb) memory read 0x00000001005b65e0
0x1005b65e0: a9 65 5b 00 01 80 1d 00 80 62 5b 00 03 00 00 00
0x1005b65f0: 70 e9 10 9e ff 7f 00 00 00 00 00 00 00 00 00 00

foo 包含 0x0000007fff9e10e970,十进制为 140735845296496,对应于:

(lldb) frame variable -L pointee
0x00000001005e2e18: (testmem.C) pointee = 0x00000001005b65e0 {
0x00000001005b65f0: foo = 140735845296496 // this
0x00000001005b65f8: bar = 0
}

并且由于该数据不是由我的程序分配的,我们无权访问它,因此出现 EXC_BAD_ACCESS 错误。

现在生活变得有意义了😂。

关于swift - UnsafeMutableRawPointer 到 UnsafeMutablePointer<T> : EXC_BAD_ACCESS on pointee,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46310272/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com