OC中栈和堆内存区别解析

内存管理

移动设备的内存及其有限,每一个APP所能占用的内存是有限制的

什么行为会增加APP的内存占用
  • 创建一个oc对象
  • 定义一个变量
  • 调用一个函数或者方法
内存管理范围
  • 任何继承了NSObject的对象
  • 对其它非对象类型无效
  • 简单来说:
    • 只有oc对象需要进行内存管理
    • 非oc对象类型比如基本数据类型不需要进行内存管理

引入堆和栈的概念

  • 所以问题就来了,为什么OC对象需要进行内存管理,而其它非对象类型比如基本数据类型就不需要进行内存管理呢?
  • 只有OC对象才需要进行内存管理的本质原因?

    因为:Objective-C的对象在内存中是以堆的方式分配空间的,并且堆内存是由你释放的,就是release
    OC对象存放于堆里面(堆内存要程序员手动回收)
    非OC对象一般放在栈里面(栈内存会被系统自动回收)

    堆里面的内存是动态分配的,所以也就需要程序员手动的去添加内存、回收内存

堆是所有程序共享的内存,当N个这样的内存得不到释放,堆区会被挤爆,程序立马瘫痪。这就是内存泄漏

这里要知道的是:系统在堆区只会记录某一个区域被使用了,并不会管你是什么类型的(匿名访问)。

那么,既然是匿名访问,堆不管你的类型了,那怎么区分这块内存是什么类型的呢?

简单:什么类型指针指向这块内存,这块内存就是什么类型的。


举例说明1

该代码块在内存中的表现形式如下图


图中可以看到,栈里面存放的是非对象的基本数据类型,堆内存存放着oc对象


当代码块一过,里面的a,b,*c指针都会被系统编译器自动回收,因为它存放在栈里面,而OC对象则不会被系统回收,因为它存放堆里面,堆里面的内存是动态存储的,所以需要程序员手动回收内存


举例说明2


变量 i 和 j 就是保存在栈区里的

有一句话如是说:在OC中,默认不带*号的都是保存在栈区的。

在这里,变量名其实就是变量保存在栈区的内存地址的别名。

那么,这个程序运行时在栈区是如何出入的呢?

程序在栈区的出入步骤:

程序运行执行main函数,i首先进入栈区,位于最底部。然后j进入栈区,printf调用函数sum(i, j)紧随其后进入栈区。

函数sum(int x, int y)中的参数,从右到左依次进入栈区。先是y再是x。

栈区存储样式:


当程序运行结束后,栈区内的所有元素会从上到下的依次出栈,栈会恢复到原始状态。

栈的先进后出方式,会特别整齐的存取,不会产生内存碎片。


总结区别
  • 按管理方式分
    • 对于栈来讲,是由系统编译器自动管理,不需要程序员手动管理
    • 对于堆来讲,释放工作由程序员手动管理,不及时回收容易产生内存泄露
  • 按分配方式分
    • 堆是动态分配和回收内存的,没有静态分配的堆
    • 栈有两种分配方式:静态分配和动态分配
      • 静态分配是系统编译器完成的,比如局部变量的分配
      • 动态分配是有alloc函数进行分配的,但是栈的动态分配和堆是不同的,它的动态分配也由系统编译器进行释放,不需要程序员手动管理
参考:http://www.jianshu.com/p/c8e1d91dda99和http://blog.csdn.net/liuhang03/article/details/49826205
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值