I am using withUnsafeMutablePointer to get raw pointer from Data. Once I get a Pointer I follow these steps:
- I create a Wrapper using that Pointer.
- After that I increase it ARC and pass it as a opaque to C++
When I was on First Step if my thread get suspended and after some time if it resumes then is there a possibility that the Memory will get freed due to ARC.
Adding basic Code Flow depicting what i am doing.
public class DataHolder {
public init () {}
public var data_wrapper : Data?
}
func InternalReceiveHandler (_ pContent : Data?) -> Void {
var holder : DataHolder = DataHolder.init ()
withUnsafeMutablePointer (to : &pContent) { data_pointer in
holder.data_wrapper = Data.init (noBytesCopy : data_pointer, count : no_of_bytes, deallocator : .none)
return Unmanaged.passRetained (holder).toOpaque ()
}
}
Is there a possibility that when I am creating the wrapper my thread get suspended and when it get resumed the Memory the pointer was pointing can be freed by ARC.
I’m not sure I understand the snippet you posted. Specifically, you have a return
statement at the end of the closure but it’s not clear what that’s for. So, I’m going to post some examples of stuff that’s safe and stuff that’s not.
Before I do that, however, I’m concerned about this:
withUnsafeMutablePointer (to : &pContent) { … }
That doesn’t get you a pointer to the bytes held in the Data
value, but rather a pointer to the Data
value itself. That’s generally not what you want. Rather, you’d typically write this:
data.withUnsafeBytes { … }
With that caveat, let’s look at some examples. Imagine you have a C function that takes a pointer and a counter. It gets imported into Swift like so:
func myLegacyCFunction(_ pointer: UnsafeRawPointer, _ count: Int)
You then want to call it with the bytes in a Data
value. This code is correct:
func testOK(data: Data) {
data.withUnsafeBytes { buf in
myLegacyCFunction(buf.baseAddress!, buf.count)
}
}
OTOH, this code is incorrect:
func testNG(data: Data) {
let pointer = data.withUnsafeBytes { buf in
buf.baseAddress!
}
myLegacyCFunction(pointer, data.count)
}
The buf.baseAddress
value is only valid in the closure. The testNG(…)
function escapes the value from the closure, and thus will encounter Very Bad Things™.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"