How ARC works withUnsafeMutablePointer Interface.

I am using withUnsafeMutablePointer to get raw pointer from Data. Once I get a Pointer I follow these steps:

  1. I create a Wrapper using that Pointer.
  2. 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.
Answered by DTS Engineer in 801697022

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"

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"

Hi @DTS Engineer, withUnsafeBytes is Deprecated with data Now, is there any other alternative way to do this. Also just wanted to confirm that within the closure the Pointer to the bytes will always remain valid and it's ARC will not be decremented any how?

withUnsafeBytes is Deprecated with data Now

withUnsafeBytes(_:) is not deprecated. Well, the specific flavour I’m using is not deprecated. I’m using this and the deprecated one is this.

You are not the first person to be confused by this )-:

Also just wanted to confirm that within the closure the Pointer to the bytes will always remain valid and it's ARC will not be decremented any how?

Correct. The unsafe buffer passed to the closure remains valid until the closure returns.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer Thanks I got the clarity regarding the ARC. I have a usecase where I get a Data Object in the CallBack I Register during the receive call. I want to pass the same Data Object to C++ without creating a Copy and ensuring that it remains valid until i am done with my operations in C++. Is there a way for that?

I want to pass the same Data Object to C++ without creating a Copy and ensuring that it remains valid until i am done with my operations in C++.

Not with Data.

You can, however, switch to the receiveDiscontiguous(minimumIncompleteLength:maximumLength:completion:) method, which passes you a DispatchData value. That is a struct, but you can bridge it to an object of type __DispatchData. That object is equivalent to the dispatch_data_t object you use in C-based languages, allowing you to use routines like dispatch_data_create_map.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How ARC works withUnsafeMutablePointer Interface.
 
 
Q