iOS内存管理(内存布局/nonpointer/sidetable/alloc/init/retain/release/weak/dealloc/自动释放池)
内容提要
本文总结了iOS内存管理的相关知识,包括内存布局、栈区、堆区、大局区、常量区、代码段等。还介绍了引用计数、自动释放池、弱引用等概念和相关操作。文章提到了在使用autorelease时需要注意的情况。
延伸解读
内存分区特性与指针安全
文章指出,代码区、常量区、全局区在App启动后大小固定,指向这些区的指针不会因内存释放而崩溃;而堆区和栈区时刻变化,堆的创建销毁、栈的弹入弹出都可能导致指针指向已释放内存,形成野指针。因此,使用指向堆或栈的指针时,必须确认内存是否有效,否则可能引发程序崩溃。
引用计数的存储与读取机制
在arm64架构下,isa指针经过优化,引用计数优先存储在isa的extra_rc中(19位),超出部分才存到SideTable。retainCount方法返回的是1加上extra_rc和SideTable中的值,因此alloc创建的对象打印引用计数为1,但alloc本身并未设置引用计数,init也只是返回对象。这解释了为什么alloc后引用计数看似为1。
weak引用的底层处理流程
weak变量通过objc_initWeak、storeWeak等函数管理。storeWeak会获取新旧SideTable,加锁后移除旧弱引用、注册新弱引用,并设置isa的weakly_referenced标志。当对象dealloc时,weak_clear_no_lock会将所有指向它的弱引用置为nil,避免野指针。这一机制确保了weak引用的安全性。
自动释放池与RunLoop的协作
自动释放池以栈结构通过双向链表组织,每个Page占4096字节。主线程RunLoop注册了两个Observer:Entry时push池,BeforeWaiting时pop并push新池,Exit时pop池。因此autorelease对象通常在RunLoop循环结束时释放。手动添加@autoreleasepool可在循环中及时释放临时对象,降低内存峰值。
Q&A
iOS内存管理的主要内存区域有哪些?
iOS内存管理主要包括栈区、堆区、大局区、常量区和代码段。
什么是引用计数,它在iOS内存管理中有什么作用?
引用计数是管理对象生命周期的方式,当引用计数为0时,系统会释放对象。
如何使用alloc和init方法创建对象?
alloc方法分配内存但不设置引用计数,init方法会将引用计数设置为1。
weak引用的作用是什么?
weak引用用于避免循环引用,确保对象可以被正确释放。
dealloc方法在内存管理中有什么作用?
dealloc方法用于释放对象内存,涉及清理弱引用和引用计数。
自动释放池的工作原理是什么?
自动释放池用于管理临时对象的内存,嵌套使用时会影响内存释放时机。