Another reason of C pointers are called unsafe
is there is no auto memory management for them. We have to manage the memory in a behaviour prior to ARC, by allocating and releasing memory manually. If we failed to do the right things, the program will fail us with a crash or leak.
A correct way to begin to use a pointer from the beginning would be alloc
it first and then initialize
followed. After using it, we should take into consideration the fact that manually releasing is required. If not careful, it is easy to write like this:
This is wrong code
class MyClass { var a = 1 deinit { print("deinit") } } var pointer: UnsafeMutablePointer<MyClass>! pointer = UnsafeMutablePointer<MyClass>.alloc(1) pointer.initialize(MyClass()) print(pointer.memory.a) // Output: 1 pointer = nil
Although we set pointer
to nil
at last, UnsafeMutablePointer
is not auto memory managed, the memory pointed by pointer
is not released or collected. This can be proven by deinit
of MyClass
not get called. Notice: you have to run this code in a project other than in a Playground, which could not be used to check memory issues. The code above leaks memory. The correct way is adding destroy
and dealloc
to the end, which will release the pointed memory.
var pointer: UnsafeMutablePointer<MyClass>!
pointer = UnsafeMutablePointer<MyClass>.alloc(1)
pointer.initialize(MyClass())
print(pointer.memory.a)
pointer.destroy()
pointer.dealloc(1)
pointer = nil
// Output:
// 1
// deinit
If we try to access pointer
or call dealloc
on the pointer again after dealloc
called, we will receive an EXC_BAD_ACCESS
, which is not surprising at all. We are all aware of this kind of crash in the manually memory management age.
When handling memory management of these pointer types, we must follow a basic principle: the one who creates the pointer is responsible for releasing it. That means, dealloc
and destroy
should be used in pair with alloc
and initialize
respectively. If a pointer is not owned (created) by you, you are not expected to release it. A common case is that we get a pointer by calling a method, expect for explicitly mentioned in the documentation, you should not try to manage its memory state:
var x:UnsafeMutablePointer<tm>!
var t = time_t()
time(&t)
x = localtime(&t)
x = nil
At last, although we are using alloc
and dealloc
here, we can also use malloc
or calloc
to create the pointer. If so, we should use free
instead of dealloc
when releasing the pointer.
That's all. Good luck!