执行以下操作时,我从Address Sanitizer收到错误消息:
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)有关,但是我没有看到如何分配错误的内存大小,这会导致堆头文件或数据受到严重破坏。
更新-请参见下面的答案
好像我需要一个空终止符,因为指针中的最后一个字节或字符串将不知道指针的结尾。
答案 0 :(得分:1)
其他选项...
您可以从Data
创建UnsafeMutableRawPointer
:
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)
请尝试。
答案 1 :(得分:0)
弄清楚了。
根据String(cString: fooParam)
- 参数cString:指向以空值终止的UTF-8代码序列的指针。
如果您要发送的数据不是以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