Home > Enterprise >  Value type reallocation
Value type reallocation

Time:10-01

Consider I have a struct Person with a property "name". Why changing the name property results in a new memory address?

struct Person {
    var name = "Alex"
}

var person = Person()
withUnsafePointer(to: person) { print($0)
} // 0x000000016fdff248

person.name = "John"
withUnsafePointer(to: person) { print($0)
} // 0x000000016fdff208

CodePudding user response:

You're calling the wrong version of withUnsafePointer(to:). If you call the right one, it behaves as you expect (though it is not promised to do so). The one you're calling is:

func withUnsafePointer<T, Result>(to value: T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result

That passes a copy of value to the function. It doesn't even require that there be memory allocated; it'll allocate memory itself to ensure that there's something to point to:

// Who needs a variable?
withUnsafePointer(to: 4) { print($0) }  // 0x000000016fdff348 
withUnsafePointer(to: 4) { print($0) }  // 0x000000016fdff340

But there's also an inout version of this function, and I expect it's what you really meant to call:

func withUnsafePointer<T, Result>(to value: inout T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result

That expects a reference to the value. Note the use of & here, and that it behaves as you're expecting:

var person = Person()
withUnsafePointer(to: &person) { print($0) } // 0x0000000100008018

person.name = "John"
withUnsafePointer(to: &person) { print($0) } // 0x0000000100008018

Do not read too much into this. The compiler does not promise stable addresses except in very specific cases as MartinR noted. There is no safe way to hold onto a pointer to a struct (and references are not quite the same thing as pointers in any case). Structs are not even promised to allocate memory. Every Int is a struct, after all. But if you use the inout version of this call, I think the mystery disappears.

  • Related