释放UnsafeMutableBufferPointer <uint8>值

时间:2015-09-07 14:53:12

标签: swift memory memory-management memory-leaks swift2

我正在实现纯粹的Swift NSData替代方案。下面是我的Swift 2代码的一部分。据我所知,Data实例取消初始化不会destroy()缓冲区指向的dealloc()block字节。 那么,有没有办法在缓冲区指针上调用destroydealloc()以防止在Data实例取消初始化之前发生内存泄漏?

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)
    }
}

2 个答案:

答案 0 :(得分:5)

您可以使用class来解决此问题。 以下是一个如何做到这一点的例子 Friday Q&A 2015-04-17: Let's Build Swift.Array

  

可以使用提供class的{​​{1}}解决销毁问题。该   指针可以在那里被销毁。 deinit没有价值语义,   但是我们可以通过使用class来实现   class,并将struct作为外部接口公开   阵列。这看起来像:

struct
     

然后,您可以在class ArrayImpl<T> { var ptr: UnsafeMutablePointer<T> deinit { ptr.destroy(...) ptr.dealloc(...) } } struct Array<T> { var impl: ArrayImpl<T> } 上编写转发给实现的方法   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)
    }
}

输出:

deinit
finished

答案 1 :(得分:1)

感谢@Martin R answer。 我已将class AutoreleasingMutableBufferPointer<T>添加为struct UnsafeMutableBufferPointer<T>的容器和解除分配器。 这是工作代码:

public class AutoreleasingMutableBufferPointer<T> {
    public var buffer: UnsafeMutableBufferPointer<T>

    public init(start pointer: UnsafeMutablePointer<T>, count length: Int) {
        self.buffer = UnsafeMutableBufferPointer<T>(start: pointer, count: length)
    }

    public init(buffer: UnsafeMutableBufferPointer<T>) {
        self.buffer = buffer
    }

    deinit {
        self.buffer.baseAddress.destroy(buffer.count)
        self.buffer.baseAddress.dealloc(buffer.count)
    }
}

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

extension Data {
    public init(bytes: UnsafeMutablePointer<Block>, length: Int) {
        let bytesCopy = UnsafeMutablePointer<Block>.alloc(length)
        bytesCopy.initializeFrom(bytes, count: length)
        self.blocks = AutoreleasingMutableBufferPointer<Block>(start: bytesCopy, count: length)
    }
}