我有一个C char *cArray
并且它的长度,我需要将其转换为NSData
我这样做了:
var data: NSData? = NSData(bytesNoCopy: cArray, length: Int(length))
它正在发挥作用。问题是这会导致一些内存泄漏。我不知道为什么,但我可以在分配工具上看到它是malloc 64字节,并且在函数完成或我将其设置为null时不释放它。
这个代码被大量调用,所以我需要它无泄漏。我该怎么做才能防止泄漏?
编辑:这是代码
func on_data_recv_fn(buf: UnsafeMutablePointer<CChar>, length: CInt, user_data: UnsafeMutablePointer<Void>) -> CInt {
guard buf != nil else {
NSLog("on_data_recv_fn buf is nil")
return -1
}
//var data: NSData? = NSData(bytesNoCopy: buf, length: Int(length), freeWhenDone: true)
var data: NSData? = NSData(bytesNoCopy: buf, length: Int(length))
let succeededWriting = Int(PacketTunnelProvider.sendPackets(data!))
data = nil
return CInt(succeededWriting)
}
根据记忆仪器,这里有泄漏。 sendPackets函数不保存数据,因此不存在问题。
答案 0 :(得分:2)
嗯,似乎如果我使用autoreleasepool,由于某些原因,一切都可以。
答案 1 :(得分:1)
Objective-C支持的类型的内存管理是一个庞大而有趣的话题。例如,见:
您可能还会发现此问题很有用:
Is it necessary to use autoreleasepool in a Swift program?
另外,我认为如果buf
传递给on_data_recv_fn
的{{1}}是由某些C代码动态分配的,那么后来会尝试释放它。另一个危险的可能性:该函数是在Swift中实现的回调并由C代码调用。在这种情况下,buf
可能在堆栈中。
我没有玩过任何这些场景,但根据NSData
文档,bytesNoCopy
初始值设定项使NSData
取得内存的所有权,然后取消分配;它假设内存是使用malloc()
分配的,因此任何不是malloc'd
的内存都不应该用于使用此初始化程序构造NSData
。见https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/#//apple_ref/occ/instm/NSData/initWithBytesNoCopy:length:
还有其他NSData
初始化程序可以复制缓冲区,在这些情况下可以更安全。