iOS的内存分区

iOS中内存分区

iOS内存模块

应用在内存中运行,不同的类型在内存处于不同分区。
按照内存地址由低到高分为:代码区、常量区、全局/静态区、栈、 堆、栈、全局区/静态区、常量区、代码区

如下图:

iOS内存分配

代码区

在内存的最低地址区间,用于存储编译完成后代码部分。

常量区

用于常量内存分配,由系统维护

全局区/静态区(static)

主要为全局变量和静态变量分配内存,分为、初始值和未初始过的两个部分。

堆(heap)

由开发者分配释放(或者编译器自动添加释放命令),不释放可能引起内存泄露。分配时,堆内采用链表形式管理内存段,需要分配时对链表进行遍历,找到空间大于申请的节点分配给开发者,然后在链表中删除节点。

特点:

  • 堆区分配使用alloc, Swift的引用类型内存在堆区
  • 开发者自行管理,ARC由编译器自动添加管理命令
  • 地址由低到高,内存分配靠遍历链表查找

优点

  • 可以使用引用计数让多个ower拥有(只有heap内对象才可以用"引用计数")

栈(stack)

由编译器管理自动释放,如方法内变量,局部变量等。分配时只要栈的空间大于对象申请的空间,就会提供该段内存,否则报栈溢出。

对于一个方法,在方法作用域内形成一个栈帧(stack frame)(包含参数,局部变量,返回值等),执行完方法后,栈帧弹出,里面所有内存销毁。

特点:

  • 存放局部变量,函数跳转地址,指针地址,值类型对象等,先进先出,出了作用域就销毁。
  • 开发者不需要管理栈区内存,分配由高到低。
  • 内存分配是连续的。

优点

  • 速度快,管理简单,有严格生命周期
  • 一般不会出现内存泄露问题(还是有小机率造成循环引用的内存泄露)

缺点

  • 不灵活,创建时候是多大以后就多大,且owner只有一个。

相关问题

block使用copy属性关键字的原因

block定义后存在栈区,如果作用域改变,就会导致block可能被回收,所以当赋值操作时,进行copy操作,将block拷贝到堆区,保证使用过程不会被回收。

weak对象释放时自动置为nil实现

系统有一个weakhash表,将weak标记的对象地址注册到表中,如果对象被destory销毁,则在weak表中将改对象地址置为nil。

苹果内存引用实现

通过引用计数hash表来实现,对hash表进行操作来实现。引用计数表记录内存地址,以便找到对象。

Swift值类型与引用类型内存分配区别

值类型直接在栈区分配对象的内存,引用类型(class)先在堆分配对象内存,然后再在栈区分配对象的指针。

stack
struct Point {
 var x, y:Double
 func draw() {}
}
let point1 = Point(x:0, y:0) //进行point1初始化,开辟栈内存
var point2 = point1 //初始化point2,拷贝point1内容,开辟新内存
point2.x = 5 //对point2的操作不会影响point1
// use `point1`
// use `point2`

point1和point2为两片不同内存对象。

结构体(值类型)内存分配

heap
// Class
class Point {
 var x, y:Double
 func draw() {}
}
let point1 = Point(x:0, y:0) //在堆区分配内存,栈区只是存储地址指针
let point2 = point1 //不产生新的实例,而是对point2增加对堆区内存引用的指针
point2.x = 5 //因为point1和point2是一个实例,所以point1的值也会被修改
// use `point1`
// use `point2`

point1与point2指向同一个堆对象。

类内存分配

参考

iOS开发堆栈你理解多少

深入剖析Swift性能优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值