Consider this fragment:
import Foundation
struct Foo {
var a: Int64 = 1
var b: Int64 = 2
mutating func secondValuePointer() -> UnsafeMutablePointer<Int> {
return withUnsafeMutablePointer(to: &self) { p in
return UnsafeMutableRawPointer(p) // typed pointer -> raw pointer
.advanced(by: 8) // adjust raw pointer
.assumingMemoryBound(to: Int.self) // raw pointer -> typed pointer
}
}
}
func foo() {
var v = Foo()
print(v) // Foo(a: 1, b: 2)
print(v.secondValuePointer().pointee) // 2
v.secondValuePointer().pointee = 3
print(v) // Foo(a: 1, b: 3)
}
foo()
Assuming there is no error in the pointer math and the advanced pointer points to a proper location and properly typed value, does this still trigger UB and work by chance when it returns a pointer like that, or is it ok?
I think it works by chance, and this:
v.secondValuePointer() /* ... */ .pointee
could break if compiler (for whatever reason) decides to move v to another location and place something else in that location after v.secondValuePointer() called and before .pointee being called. Is this analysis correct?
Is it possible to fix this fragment without changing it significantly (e.g. without changing it to take a callback and do the work inside that callback)?