我正在实现纯粹的Swift NSData
替代方案。下面是我的Swift 2代码的一部分。据我所知,Data
实例取消初始化不会destroy()
缓冲区指向的dealloc()
和block
字节。
那么,有没有办法在缓冲区指针上调用destroy
和dealloc()
以防止在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)
}
}
答案 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)
}
}