执行以下操作时,我收到地址清理器的错误:
let pointer = UnsafeMutableRawPointer.allocate(byteCount: 4, alignment: 1)
pointer.storeBytes(of: 77, as: UInt8.self)
pointer.advanced(by: 1).storeBytes(of: 105, as: UInt8.self)
(pointer+2).storeBytes(of: 107, as: UInt8.self)
(pointer+3).storeBytes(of: 101, as: UInt8.self)
let typedPointer = pointer.bindMemory(to: UInt8.self, capacity: 4)
let readableData = String(cString: typedPointer)
我得到堆缓冲区溢出,但我不明白为什么。在我的实际代码中,我有一个更复杂的指针,但即使在这个简单的示例中,我也始终如一地遇到这个问题。我认为它与 String(cString:typedPointer( 有关,但我没有看到我如何分配错误的内存大小,从而导致任何堆头或数据被踩踏。
更新 - 请参阅下面的答案
看起来我需要一个空终止符作为指针中的最后一个字节,否则字符串将不知道指针的结束位置。
其他选项...
您可以从UnsafeMutableRawPointer
创建Data
:
let pointer = UnsafeMutableRawPointer.allocate(byteCount: 4, alignment: 1)
pointer.storeBytes(of: 77, as: UInt8.self)
pointer.advanced(by: 1).storeBytes(of: 105, as: UInt8.self)
(pointer+2).storeBytes(of: 107, as: UInt8.self)
(pointer+3).storeBytes(of: 101, as: UInt8.self)
let data = Data(bytes: pointer, count: 4)
let readableData = String(data: data, encoding: .utf8)
否则,String.init(bytes:encoding:)
是另一个不声明以 null 结尾的序列的初始值设定项:
let pointer = UnsafeMutableRawPointer.allocate(byteCount: 4, alignment: 1)
pointer.storeBytes(of: 77, as: UInt8.self)
pointer.advanced(by: 1).storeBytes(of: 105, as: UInt8.self)
(pointer+2).storeBytes(of: 107, as: UInt8.self)
(pointer+3).storeBytes(of: 101, as: UInt8.self)
let urbp = UnsafeRawBufferPointer(start: pointer, count: 4)
let readableData = String(bytes: urbp, encoding: .utf8)
请尝试。
通了。
根据String(cString: fooParam)
的文件
- 参数 cString:指向以 null 结尾的 UTF-8 代码序列的指针。
如果要发送的数据不是以 null 结尾的,则此初始值设定项将不知道指针数据的结束位置,并且会出现"意外行为",有时失败,有时成功。
解决方案是,如果您尝试传入的数据不是以 null 结尾的,则添加 null 终止符。
例如:
let pointer = UnsafeMutableRawPointer.allocate(byteCount: 5, alignment: 1)
pointer.storeBytes(of: 77, as: UInt8.self)
pointer.advanced(by: 1).storeBytes(of: 105, as: UInt8.self)
(pointer+2).storeBytes(of: 107, as: UInt8.self)
(pointer+3).storeBytes(of: 101, as: UInt8.self)
(pointer+4).storeBytes(of: 0, as: UInt8.self)
let typedPointer = pointer.bindMemory(to: UInt8.self, capacity: 5)
let readableData = String(cString: typedPointer)
在我实际做的事情中,我没有原始引用,而是键入的引用。同样的事情是通过做来实现的
somePointer.advanced(by: 4).pointee = 0