Swift 有时方法会失败,并出现致命错误:UnsafeMutablePointer.initialize重叠范围

Swift 有时方法会失败,并出现致命错误:UnsafeMutablePointer.initialize重叠范围,swift,unsafemutablepointer,Swift,Unsafemutablepointer,我用下面的代码将Swift 5中的一些数据解压回字符串。该方法大部分工作正常,但有时会失败,并显示以下错误消息: 线程1:致命错误:UnsafeMutablePointer.initialize重叠范围 extension Data { func decompress(destinationSize: Int) -> String? { let destinationBuffer = UnsafeMutablePointer<UInt8>.all

我用下面的代码将Swift 5中的一些
数据
解压回
字符串
。该方法大部分工作正常,但有时会失败,并显示以下错误消息:

线程1:致命错误:UnsafeMutablePointer.initialize重叠范围

extension Data
{
    func decompress(destinationSize: Int) -> String?
    {
        let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: destinationSize)

        let decodedString = self.withUnsafeBytes
        {
            unsafeRawBufferPointer -> String? in

            let unsafeBufferPointer = unsafeRawBufferPointer.bindMemory(to: UInt8.self)
            if let unsafePointer = unsafeBufferPointer.baseAddress
            {
                let decompressedSize = compression_decode_buffer(destinationBuffer, destinationSize, unsafePointer, self.count, nil, COMPRESSION_ZLIB)

                if decompressedSize == 0
                {
                    return String.empty
                }

                let string = String(cString: destinationBuffer)
                let substring = string.substring(0, decompressedSize)

                return substring
            }

            return nil
        }

        return decodedString
    }
}

有人能解释一下这(有时)失败的原因吗?

我已切换到以下代码,现在一切正常(Swift 5):

导入压缩
扩展数据
{
func compress()->数据?
{
返回self.withUnsafeBytes
{
中的数据字节
让sourcePtr:UnsafePointer=dataBytes.baseAddress!.assumingmemorybind(to:UInt8.self)
返回self.perform(操作:压缩\流\编码,源:sourcePtr,sourceSize:self.count)
}
}
func decompress()->数据?
{
返回self.withUnsafeBytes
{
unsafeRawBufferPointer->Data?在中
让unsafeBufferPointer=unsafeRawBufferPointer.bindMemory(to:UInt8.self)
如果让unsafePointer=unsafeBufferPointer.baseAddress
{
返回self.perform(操作:压缩\流\解码,源:unsafePointer,源大小:self.count)
}
归零
}
}
fileprivate func perform(操作:压缩\流\操作,源:UnsafePointer,源大小:Int,预加载:Data=Data())->Data?
{
guard sourceSize>0 else{return nil}
让streamBase=unsafemeutablepointer.allocate(容量:1)
延迟{streamBase.deallocate()}
var stream=streamBase.pointee
let status=compression\u stream\u init(&stream,operation,compression\u ZLIB)
保护状态!=压缩状态错误{return nil}
延迟{compression\u stream\u destroy(&stream)}
var结果=预加载
变量标志:Int32=Int32(压缩\u流\u FINALIZE.rawValue)
设blockLimit=64*1024
var bufferSize=Swift.max(sourceSize,64)
如果sourceSize>blockLimit
{
缓冲区大小=块限制
}
let buffer=unsafemeutablepointer.allocate(容量:bufferSize)
延迟{buffer.deallocate()}
stream.dst_ptr=缓冲区
stream.dst_size=缓冲区大小
stream.src_ptr=源
stream.src_size=sourceSize
虽然是真的
{
交换机压缩\u流\u进程(&流,标志)
{
案例压缩\u状态\u正常:
guard stream.dst_size==0 else{return nil}
追加(缓冲区,计数:stream.dst_ptr-buffer)
stream.dst_ptr=缓冲区
stream.dst_size=缓冲区大小
如果标志==0&&stream.src\u大小==0
{
flags=Int32(压缩\u流\u FINALIZE.rawValue)
}
案例压缩\u状态\u结束:
追加(缓冲区,计数:stream.dst_ptr-buffer)
返回结果
违约:
归零
}
}
}
}

我已切换到以下代码,现在一切正常(Swift 5):

导入压缩
扩展数据
{
func compress()->数据?
{
返回self.withUnsafeBytes
{
中的数据字节
让sourcePtr:UnsafePointer=dataBytes.baseAddress!.assumingmemorybind(to:UInt8.self)
返回self.perform(操作:压缩\流\编码,源:sourcePtr,sourceSize:self.count)
}
}
func decompress()->数据?
{
返回self.withUnsafeBytes
{
unsafeRawBufferPointer->Data?在中
让unsafeBufferPointer=unsafeRawBufferPointer.bindMemory(to:UInt8.self)
如果让unsafePointer=unsafeBufferPointer.baseAddress
{
返回self.perform(操作:压缩\流\解码,源:unsafePointer,源大小:self.count)
}
归零
}
}
fileprivate func perform(操作:压缩\流\操作,源:UnsafePointer,源大小:Int,预加载:Data=Data())->Data?
{
guard sourceSize>0 else{return nil}
让streamBase=unsafemeutablepointer.allocate(容量:1)
延迟{streamBase.deallocate()}
var stream=streamBase.pointee
let status=compression\u stream\u init(&stream,operation,compression\u ZLIB)
保护状态!=压缩状态错误{return nil}
延迟{compression\u stream\u destroy(&stream)}
var结果=预加载
变量标志:Int32=Int32(压缩\u流\u FINALIZE.rawValue)
设blockLimit=64*1024
var bufferSize=Swift.max(sourceSize,64)
如果sourceSize>blockLimit
{
缓冲区大小=块限制
}
let buffer=unsafemeutablepointer.allocate(容量:bufferSize)
延迟{buffer.deallocate()}
stream.dst_ptr=缓冲区
stream.dst_size=缓冲区大小
stream.src_ptr=源
stream.src_size=sourceSize
虽然是真的
{
交换机压缩\u流\u进程(&流,标志)
{
案例压缩\u状态\u正常:
guard stream.dst_size==0 else{return nil}
追加(缓冲区,计数:stream.dst_ptr-buffer)
stream.dst_ptr=缓冲区
stream.dst_size=缓冲区大小
如果标志==0&&stream.src\u大小==0
{
flags=Int32(压缩\u流\u FINALIZE.rawValue)
}
案例压缩\u状态\u结束:
追加(缓冲区,计数:stream.dst_ptr-buffer)
返回
let string = String(cString: destinationBuffer)
import Compression

extension Data
{
    func compress() -> Data?
    {
        return self.withUnsafeBytes
        {
            dataBytes in

            let sourcePtr: UnsafePointer<UInt8> = dataBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)

            return self.perform(operation: COMPRESSION_STREAM_ENCODE, source: sourcePtr, sourceSize: self.count)
        }
    }

    func decompress() -> Data?
    {
        return self.withUnsafeBytes
        {
            unsafeRawBufferPointer -> Data? in

            let unsafeBufferPointer = unsafeRawBufferPointer.bindMemory(to: UInt8.self)
            if let unsafePointer = unsafeBufferPointer.baseAddress
            {
                return self.perform(operation: COMPRESSION_STREAM_DECODE, source: unsafePointer, sourceSize: self.count)
            }

            return nil
        }
    }

    fileprivate func perform(operation: compression_stream_operation, source: UnsafePointer<UInt8>, sourceSize: Int, preload: Data = Data()) -> Data?
    {
        guard sourceSize > 0 else { return nil }

        let streamBase = UnsafeMutablePointer<compression_stream>.allocate(capacity: 1)
        defer { streamBase.deallocate() }
        var stream = streamBase.pointee

        let status = compression_stream_init(&stream, operation, COMPRESSION_ZLIB)
        guard status != COMPRESSION_STATUS_ERROR else { return nil }
        defer { compression_stream_destroy(&stream) }

        var result = preload
        var flags: Int32 = Int32(COMPRESSION_STREAM_FINALIZE.rawValue)
        let blockLimit = 64 * 1024
        var bufferSize = Swift.max(sourceSize, 64)

        if sourceSize > blockLimit
        {
            bufferSize = blockLimit
        }

        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
        defer { buffer.deallocate() }

        stream.dst_ptr  = buffer
        stream.dst_size = bufferSize
        stream.src_ptr  = source
        stream.src_size = sourceSize

        while true
        {
            switch compression_stream_process(&stream, flags)
            {
                case COMPRESSION_STATUS_OK:
                    guard stream.dst_size == 0 else { return nil }
                    result.append(buffer, count: stream.dst_ptr - buffer)
                    stream.dst_ptr = buffer
                    stream.dst_size = bufferSize

                    if flags == 0 && stream.src_size == 0
                    {
                        flags = Int32(COMPRESSION_STREAM_FINALIZE.rawValue)
                    }

                case COMPRESSION_STATUS_END:
                    result.append(buffer, count: stream.dst_ptr - buffer)
                    return result

                default:
                    return nil
            }
        }
    }
}