[swift-users] non-mutating func that still mutates a struct, compiler not aware
Dave Abrahams
dabrahams at apple.com
Sat Aug 6 09:22:35 CDT 2016
on Sat Aug 06 2016, Raphael Sebbe <swift-users-AT-swift.org> wrote:
>> Those UnsafeMutablePointer<T>(…) calls aren’t correct. When an array is
>> implicitly converted to a pointer in Swift, the pointer is only valid for
>> the *immediate* call that it’s being passed to. In this case, that’s the
>> UnsafeMutablePointer initializer, and after that the pointer is invalid. So
>> it’s possible that either the same space is being reused for both pointers,
>> or that it’s *not* uniquing the array because it thinks it only has to
>> make an UnsafePointer<T>, or both.
>>
>> As Brent says, passing the arrays directly to the method using inout
>> semantics (&) should get you the behavior you want.
>>
>> (Yes, there should be a diagnostic for this. I’m pretty sure we have a bug
>> already, so no need to file. The Swift 3 pointer APIs make this a little
>> harder to do by accident, too.)
If you want to be safe in the general case, use
a.withUnsafe[Mutable]BufferPointer { let p = $0.baseAddress; ... }
which will force the pointer to remain valid through the execution of
the entire closure. Yes, it's syntactically a *lot* heavier than just
passing &a, but it doesn't break without warning when some maintainer
comes along and passes &a through a function.
We ought to prevent the &a -> UnsafeMutablePointer conversion trick from
working except when calling imported C APIs directly.
--
-Dave
More information about the swift-users
mailing list