内存分区注意事项:
1 在iOS中,堆区的内存是应用程序共享的,堆中的内存分配是系统负责的。
2 系统使用一个链表来维护所有已经分配的内存空间(系统仅仅纪录,并不管理具体的内容)。
3 变量使用结束后,需要释放内存,OC中是根据引用计数==0,就说明没有任何变量使用该空间,那么系统将直接收回;
4 当一个app启动后,代码区,常量区,全局区大小已固定,因此指向这些区的指针不会产生崩溃性的错误。而堆区和栈区是时时刻刻变化的(堆的创建销毁,栈的入栈出栈),所以当使用一个指针指向这两个区里面的内存时,一定要注意内存是否已经被释放,否则会产生程序崩溃(也即是野指针报错)。
5 栈区和堆区内存分配的方式
栈区:栈区内存分配包括动态分配和静态分配.静态分配时内存分配和释放都由编译器来处理.动态分配时内存的分配是alloc 的时候分配的,释放的时候是由编译器来释放的.但一般不允许栈区做动态分配内存.
堆区:内存都是动态分配的,内存的分配和释放是由程序员来管理的.
6 栈区和堆区的内存分配原理
栈区:函数执行的时候会向系统索要资源,内存随着函数的执行而分配,函数的结束而回收,只要剩余空间大于索要空间,则会自动给与内存,当索要空间大于剩余空间时,会造成 Stack Overflow 崩溃.
堆区:操作系统有一个记录空闲内存的链表.当接收到内存空间申请时,会查询链表,找到第一个空间大于申请空间的堆节点,将空间分配出去同时在链表中删除该区域.另外系统会自动回收分配空间多余的部分,放回链表中.
7 栈区和堆区的大小
栈区:是一个向低地址扩展的数据结构,是一个连续的内存区域.也就是说栈顶和栈区的容量是系统预先定好的,2M, 如果申请空间小于剩余空间,则会直接分配内存,否则会出现 Stack Overflow,
堆区:是由低向高扩展的数据结构,是一个不连续的内存区域.堆区的内存分配是由链表来决定的,链表的遍历方式是由低地址向高地址遍历,堆的大小受限于计算机的虚拟内存.
全局区/静态区,常量区和代码区的大小都是固定的,并且是在预编译的时候都确定了的.
8 栈区和堆区的内存申请效率
栈区:由编译器分配和释放,分配效率高,但程序员不能控制.
堆区:由alloc分配和释放,分配效率低,但操作灵活.
9 栈区和堆区的分配方式
栈区:由静态分配和动态分配两种方式.静态分配是由编译器完成的分配和释放的.动态分配是由 alloc 来分配,编译器来释放的.说明,栈区的动态分配是不被允许的.
堆区:堆区的内存分配都是动态分配.
案例:
UIButton *btn = [[UIButton alloc] init];
分析: OC中对象的指针存放在栈内存中,而对象 alloc出来的对象在堆内存中,栈内存中的指针通过赋值指向堆内存中的对象,然后通过栈内存的指针访问对象/变量,也就是说,我们创建一个对象的时候是用了堆和栈两个内存空间.
网友评论