[swift-users] Why does withUnsafePointer(to:) require a var argument?

Rien Rien at Balancingrock.nl
Fri Apr 28 01:51:08 CDT 2017


You will need to take full control over allocation and deallocation.

Here is a piece of code from my project SwifterSockets (on github, see the link in my signature)

public func tipReceiverLoop(
    socket: Int32,
    bufferSize: Int,
    duration: TimeInterval,
    receiver: ReceiverProtocol?) {
    
...    
    
    // Allocate the data buffer
    
    let buffer = UnsafeMutableRawPointer.allocate(bytes: bufferSize, alignedTo: 1)
    
    
    // ===============================================================================
    // This loop stays active as long as the consumer wants more and no error occured.
    // ===============================================================================
    
    var cont = true
    repeat {
        
...        
        // ================================================
        // Wait until select signals incoming data activity
        // ================================================
        
        let selres = waitForSelect(socket: socket, timeout: timeout, forRead: true, forWrite: false)
        
        switch selres {
            
...            
        case .ready:
            
            
            // =============
            // Call the recv
            // =============
            
            let bytesRead = Darwin.recv(socket, buffer.assumingMemoryBound(to: UInt8.self), bufferSize, 0)
            
            switch bytesRead {
                
...                
            case 1 ... Int.max: // Callback for the received data
                cont = receiver?.receiverData(UnsafeBufferPointer<UInt8>(start: buffer.assumingMemoryBound(to: UInt8.self), count: bytesRead)) ?? true
                
...            }
        }
        
    } while cont
    
    
    // Deallocate the data buffer
    
    buffer.deallocate(bytes: bufferSize, alignedTo: 1)
}


Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Balancingrock
Project: http://swiftfire.nl - A server for websites build in Swift






> On 28 Apr 2017, at 08:02, Rick Mann <rmann at latencyzero.com> wrote:
> 
> Yeah, okay. So: how do I do this in a way that is safe?
> 
> -- 
> Rick Mann
> rmann at latencyzero.com
> 
>> On Apr 27, 2017, at 23:00, Rien <Rien at Balancingrock.nl> wrote:
>> 
>> To address your question:
>> 
>> https://developer.apple.com/reference/foundation/data/1779823-withunsafemutablebytes
>> 
>> "Warning
>> The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure."
>> 
>> Which is exactly what you are doing, hence the code is unsafe (no pun intended).
>> 
>> Regards,
>> Rien
>> 
>> Site: http://balancingrock.nl
>> Blog: http://swiftrien.blogspot.com
>> Github: http://github.com/Balancingrock
>> Project: http://swiftfire.nl - A server for websites build in Swift
>> 
>> 
>> 
>> 
>> 
>> 
>>> On 28 Apr 2017, at 01:38, Rick Mann <rmann at latencyzero.com> wrote:
>>> 
>>> 
>>>> On Apr 27, 2017, at 01:48 , Alex Blewitt <alblue at apple.com> wrote:
>>>> 
>>> ...
>>> 
>>>> The let constant may not even be stored in a single place; if it's known to be constant it can be in-lined at the point of use and potentially unpacked and dead code elimination throw away the unused members, for example.
>>>> 
>>>> If you want to pass in a let constant into the pointer, you can create a copy of it locally in a local variable and then use that instead. However this will be in the local scope, so the pointer isn't valid after it returns.
>>> 
>>> Ah, so this brings up another issue, then. Many of the calls in the C library take a pointer to some memory and hang on to it, filling it in at a later point (they make network requests). I've been doing it like this, and it's been working, but I wonder if this is fragile:
>>> 
>>> class
>>> MyClass
>>> {
>>>  func
>>>  execute()
>>>  {
>>>      self.dataBuffer = Data(count: kLGSImageDataSize)
>>>      precondition(self.dataBuffer != nil, "Unable to allocate image buffer (\(kLGSImageDataSize) bytes)")
>>> 
>>>      var params = c_library_params_t()
>>>      params.data_capacity = self.dataBuffer!.count
>>> 
>>>      self.dataBuffer?.withUnsafeMutableBytes
>>>          { (inBuffer) -> Void in
>>>              //  This call returns immediately, but assumes
>>>              //  it can write to inBuffer later…
>>> 
>>>              self.request = c_library_call(&params, inBuffer)
>>>          }
>>> 
>>>      if self.request == nil
>>>      {
>>>          //  Error
>>>      }
>>>  }
>>> 
>>>  var             dataBuffer:     Data?
>>> }
>>> 
>>> 
>>> -- 
>>> Rick Mann
>>> rmann at latencyzero.com
>>> 
>>> 
>> 
> 



More information about the swift-users mailing list