Reputation: 43
I'm new to Swift and i don't understand how to use UnsafeMutablePointer<T?>
. Could anyone help me?
struct TestStruct {
var a = 0
}
func foo(ptr: UnsafeMutablePointer<TestStruct?>?) {
ptr?.pointee?.a = 123 // pointee is nil, but why?
}
func bar(ptr: TestStruct?) {
print("hello: \(ptr?.a)") // hello: nil
}
var ref = UnsafeMutablePointer<TestStruct?>.allocate(capacity: 1)
foo(ptr: ref)
bar(ptr: ref.pointee)
ref.deallocate(capacity: 1)
I'm allocate memory for the TestStruct
, but when i pass ref
to the foo
, pointee
points to the nil
. If i will make TestStruct
( UnsafeMutablePointer<TestStruct>
) non-optional - everything will work great - bar prints hello: 123
.
UPDATE:
Thanks to the @MartinR and @Hamish ! Working code:
struct TestStruct {
var a = 0
}
func foo(ptr: UnsafeMutablePointer<TestStruct?>?) {
ptr?.pointee?.a = 123
}
func bar(ptr: TestStruct?) {
print("hello: \(ptr?.a)")
}
var ref = UnsafeMutablePointer<TestStruct?>.allocate(capacity: 1)
ref.initialize(to: TestStruct())
foo(ptr: ref)
bar(ptr: ref.pointee)
ref.deinitialize()
ref.deallocate(capacity: 1)
Upvotes: 3
Views: 1269
Reputation: 539685
The behaviour of your program is undefined.
allocate()
returns uninitialized memory:
/// Allocates and points at uninitialized aligned memory for `count`
/// instances of `Pointee`.
///
/// - Postcondition: The pointee is allocated, but not initialized.
public static func allocate(capacity count: Int) -> UnsafeMutablePointer<Pointee>
You have to initialize it before use (and deinitialize before freeing the memory):
let ref = UnsafeMutablePointer<TestStruct?>.allocate(capacity: 1)
ref.initialize(to: TestStruct())
foo(ptr: ref)
bar(ptr: ref.pointee)
ref.deinitialize()
ref.deallocate(capacity: 1)
Here is another example where not initializing the memory actually leads to a crash:
class TestClass {
init() { print("init") }
deinit { print("deinit") }
}
let ptr = UnsafeMutablePointer<TestClass>.allocate(capacity: 1)
ptr.pointee = TestClass()
The assignment statement expects that ptr.pointee
is in the initialized state
and points to a TestClass
instance. Because of ARC (automatic
reference counting), the previously pointed-to object is released
when assigning a new value. That crashes if ptr.pointee
is
uninitialized.
Upvotes: 2