[swift-users] unsafe memory model questions

Andrew Trick atrick at apple.com
Mon Dec 12 13:08:02 CST 2016


> On Dec 11, 2016, at 2:51 PM, Ray Fix via swift-users <swift-users at swift.org> wrote:
> 
> Hello,
> 
> So bindMemory is part of the memory model and memory can only bind to one type at a time to avoid aliasing. But what does binding actually do? Is it somehow communicating with the optimizer?

Binding memory to a type tells the compiler what type the memory can hold. Normally that happens implicitly when you allocate memory for a particular type, so you don’t need to think about it (your memory below is implicitly bound to Int16). But if you’re playing around with raw memory/type punning and get the bound type wrong, future versions of the optimizer could “break” your code in very confusing ways.

> A tangentially related second question, in the following example:
> 
>   let count = 3
>   let mutablePointer = UnsafeMutablePointer<Int16>.allocate(capacity: count)
>   defer {
>     mutablePointer.deallocate(capacity: count)
>   }
> 
>   mutablePointer.initialize(to: 1234, count: count)
>   defer {
>     mutablePointer.deinitialize(count: count)  // must I do this?
>   }
> 
> Is it bad form if I don’t deinitialize and go straight to deallocate?  I can see where it is important for ref types (to update ref counts, etc).  Is it one of those things that the optimizer can remove for the case of value types?

You don’t need to deinitialize trivial types—it’s semantically legal to omit the deinitialize. But it doesn’t hurt—the optimizer will remove the call.  I think think it’s good form to deinitialize in examples where others are using your code as reference for best practice, or if the type isn’t obviously trivial; e.g. someone may add a reference to your previously trivial struct.

> Finally, if I initalize with some other means, such as with a raw buffer pointer subscript, is there any need to deinitialize?  Can such memory be considered initialized if I bind it with a type?
> 
>   // 1
>   let pointer = malloc(byteCount)
>   defer {
>     free(pointer)
>   }
> 
>   let mutableRawBufferPointer = UnsafeMutableRawBufferPointer(start: pointer, count: byteCount)

The above is essentially equivalent to:

let mutableRawBufferPointer = UnsafeMutableRawBufferPointer.allocate(bytes: byteCount, alignedTo: 16)
// alignment depends on the platform
defer {
  mutableRawBufferPointer.deallocate(bytes: byteCount, alignedTo: 16)
}
  
>   for index in mutableRawBufferPointer.indices {
>     mutableRawBufferPointer[index] = 42 + UInt8(index)
>   }

This is an interesting case because you’ve initialized memory to “raw bytes”. The memory isn’t bound to any type. The documentation talks about initialized memory always being bound to a type, but the underlying assumption is that you’ve used a typed operation to initialize the memory. Assigning bytes via a raw pointer subscript or storeBytes isn’t a typed operation.

It wouldn’t even make sense to deinitialize this memory because it doesn’t hold any typed values!

You could bulk-reinterpret that memory as some type (without loading the values), simply by binding the memory. It is only valid to reinterpret those raw bytes as a trivial type though, so you still don’t need to deinitialize.

The UnsafeRawPointer API specifies that copying raw bytes to/from nontrivially typed memory or is illegal. The only way to get around that would be calling down to memcpy/memmove. Similarly, reinterpreting (rebinding) trivial to nontrivial types is illegal.

> Perhaps there is a document or proposal somewhere that talks about these things. Sorry if I missed it.


https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md <https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md>
https://swift.org/migration-guide/se-0107-migrate.html <https://swift.org/migration-guide/se-0107-migrate.html>

The rules are codified in API doc comments, but the language is not very user-friendly. Those API docs are being worked on, so in the future you typically won’t need to refer back to the evolution proposal just to be able to understand the comments.

-Andy

> 
> Thanks as always,
> Ray
> 
> 
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20161212/e30ab5a1/attachment.html>


More information about the swift-users mailing list