Since Xcode 11.4 I get the warning message \"Initialization of \'UnsafeMutableRawPointer\' results in a dangling pointer\"
for the following code where I read an SIMD4 f
TLDR
make text array mutable (use var
instead of let
) and use withUnsafeMutableBytes
var texArray = Array<SIMD4<Float>>(repeating: SIMD4<Float>(repeating: 0), count: 1)
texArray.withUnsafeMutableBytes { texArrayPtr in
texture.getBytes(texArrayPtr.baseAddress!, bytesPerRow: (MemoryLayout<SIMD4<Float>>.size * texture.width), from: region, mipmapLevel: 0)
}
Explanation
The warning was introduced because the compiler can't make sure that data backing the pointer will not be deallocated. Consider you have a function (e.g. implemented in C) manipulating some data pointed to.
func f(_ a: UnsafeMutablePointer<Int>){
a[0] = 42
}
Then it must be made sure that memory was not deallocated until the end of the call. So when calling this function in the following way it is not safe
var a: = [1]
p: UnsafeMutablePointer<Int>(&a)
// at this point the compiler may optimise and deallocate 'a' since it is not used anymore
f(p)
Currently this won't be an issue as far as I know since local variables will not be deallocated before the end of the scope. One can illustrate the possible issue by introducing a nested scope in the following way
var p: UnsafeMutablePointer<Int>?
do {
var a = [1]
p = UnsafeMutablePointer<Int>(&a)
} // "a" will be deallocated here
// now "p" is a dangling pointer the compiler warned you of
var b = [0] // compiler will use same memory as for "a", so manipulating memory of "p" won't segfault
f(p!) // manipulate memory
print(b[0]) // prints 42 although "b" was initialised to 0
Due to the fact that b
allocates the same memory that a
was using before, the memory of b
is modified by the call to f(p!)
. So b[0]
is 42 although it was initialised to 0
and not explicitly modified.
With this illustration it should become clear why there are methods withUnsafeMutableBytes
and withUnsafeMutableBufferPointer
on Swift arrays and global functions withUnsafeMutablePointer
plus immutable variants. (I personally find it confusing that methods must be used on arrays and and global functions on structs.)
These functions make sure that memory is not deallocated (or reused) for the scope of the closure (I also created gist with some examples).