deinitialize()与deallocate()区别:为何需手动调用deinitialize?
问题
我正在首次学习手动内存管理(MRC),请问为何以下代码需要手动调用unsafe_pointer.deinitialize(count: 1)来销毁实例?若仅调用unsafe_pointer.deallocate(),实例仍会驻留在内存中,那deallocate()的作用是什么?
class Unsafe_Memory { var name = "Hello World" deinit { print("\(type(of: self)) is deinited and deallocated") } } let unsafe_pointer: UnsafeMutablePointer<Unsafe_Memory> = .allocate(capacity: 1) unsafe_pointer.pointee = Unsafe_Memory() dump(unsafe_pointer.pointee) unsafe_pointer.pointee.name = "Changed" dump(unsafe_pointer.pointee) unsafe_pointer.deinitialize(count: 1) unsafe_pointer.deallocate()
解答
1. 为什么必须调用deinitialize?
UnsafeMutablePointer.allocate(capacity: 1)仅负责分配一块原始的、未初始化的内存块,这块内存完全脱离Swift自动引用计数(ARC)的管理。当你执行unsafe_pointer.pointee = Unsafe_Memory()时,相当于在这块原始内存上构造了一个Unsafe_Memory类实例,但Swift不会自动追踪这块手动分配内存里的实例生命周期。
deinitialize(count: 1)的核心作用是:调用指定数量内存位置上实例的deinit方法,销毁这些实例,同时释放实例自身持有的所有资源(比如示例中name属性指向的字符串),并把内存标记为未初始化状态。如果跳过这一步,实例的deinit永远不会被触发,它持有的资源会一直占用内存,造成内存泄漏。
2. deallocate()的作用是什么?
deallocate()只负责把之前通过allocate分配的原始内存块归还给系统,它不会关心内存块里有没有初始化过的实例。如果直接调用deallocate()而不先执行deinitialize,内存里的Unsafe_Memory实例数据还会留在那块内存中,但这块内存已经不属于你的程序了——后续系统可能把这块内存分配给其他进程,这会导致野内存访问的风险,同时实例持有的资源也永远无法释放。
简单说,两者的分工是:deinitialize负责销毁内存里的实例(触发deinit、释放实例资源),deallocate负责回收内存本身。手动管理内存时,必须按“先销毁实例,再回收内存”的顺序操作,才能保证资源不泄漏、内存安全。
内容的提问来源于stack exchange,提问作者Steven-Carrot

