释放UnsafeMutableBufferPointer <UInt8>值

tie*_*tie 3 memory memory-leaks memory-management swift swift2

我正在实现一个纯粹的Swift NSData替代品.下面是我的Swift 2代码的一部分.据我所知,Data实例deinitialization没有destroy()和缓冲区指向的dealloc()字节block.那么,还有没有调用的任何方式destroydealloc()以防止内存泄漏之前对缓冲器指针的Data实例deinitializes?

public struct Data: DataContainer {
    public typealias Block = UInt8
    public var blocks: UnsafeMutableBufferPointer<Block>

    public init(bytes: UnsafeMutablePointer<Block>, length: Int) {
        // copy bytes
        let bytesCopy = UnsafeMutablePointer<Block>.alloc(length)
        bytesCopy.initializeFrom(bytes, count: length)
        // init byte blocks
        self.blocks = UnsafeMutableBufferPointer<Block>(start: bytesCopy, count: length)
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 5

您可以通过使用class实际实现来解决此问题.在星期五的问答2015-04-17中给出了如何做到这一点的一个例子 :让我们构建Swift.Array:

破坏可以通过使用来解决class,其提供deinit.指针可以在那里被销毁.class没有值语义,但我们可以通过使用它class来实现 struct,并将其struct作为外部接口暴露给数组.这看起来像:

class ArrayImpl<T> {
    var ptr: UnsafeMutablePointer<T>

    deinit {
        ptr.destroy(...)
        ptr.dealloc(...)
    }
}

struct Array<T> {
    var impl: ArrayImpl<T>
}
Run Code Online (Sandbox Code Playgroud)

然后Array,您可以在ArrayImpl其中编写方法,以实现 真正的工作.

将此方法应用于您的问题可能大致如下所示:

private class DataImpl {
    typealias Block = UInt8
    var blocks: UnsafeMutableBufferPointer<Block>

    init(bytes: UnsafeMutablePointer<Block>, length: Int) {
        // copy bytes
        let bytesCopy = UnsafeMutablePointer<Block>.alloc(length)
        bytesCopy.initializeFrom(bytes, count: length)
        // init byte blocks
        self.blocks = UnsafeMutableBufferPointer<Block>(start: bytesCopy, count: length)
    }

    deinit {
        print("deinit")
        blocks.baseAddress.destroy(blocks.count)
        blocks.baseAddress.dealloc(blocks.count)
    }
}

struct Data {
    typealias Block = UInt8
    private var impl : DataImpl

    init(bytes: UnsafeMutablePointer<Block>, length: Int) {
        impl = DataImpl(bytes: bytes, length: length)
    }
}
Run Code Online (Sandbox Code Playgroud)

一个简单的测试表明,这可以按预期工作,当变量超出范围时,数据会被释放:

var bytes : [UInt8] = [1, 2, 3, 4]
do {
    let data = Data(bytes: &bytes, length: bytes.count)
}
print("finished")
Run Code Online (Sandbox Code Playgroud)

输出:

deinit
finished