内存管理

一、为什么要进行内存管理

  • 移动设备的内存极其有限,每个app所能占用的内存是有限制的

  • 下列行为都会增加一个app的内存占用

    创建一个OC对象

    定义一个变量

    调用一个函数或者方法

  • 内存占用多大

    当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等

    如果app占用内存过大,系统可能会强制关闭app, 造成闪退现象, 影响用户体验

二、内存分类

  • 栈 :由编译器自动分配释放
  • 堆 :一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
  • 全局区(静态区):

    全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域

    未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

    程序结束释放
  • 常量区:另外还有一个专门放常量的地方, 程序结束释放
  • 代码区:存放二进制代码

三、内存管理

  • 如何回收那些不需要再使用的对象?

    那就得学会OC的内存管理

  • 所谓内存管理, 就是对内存进行管理, 涉及的操作有:

    分配内存 : 比如创建一个对象, 会增加内存占用

    清除内存 : 比如销毁一个对象, 能减小内存占用

  • 内存管理的管理范围

    任何继承了NSObject的对象

    对其他非对象类型无效(int、char、float、double、struct、enum等 )

  • 只有OC对象才需要进行内存管理的本质原因

    OC对象存放于堆里面

    非OC对象一般放在栈里面(栈内存会被系统自动回收)

四、堆和栈

堆和栈的区别:(借用网上的一个很好的比喻)

  • 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
  • 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。 (经典!)

代码示例

    int main(int argc, const char * argv[])
{
@autoreleasepool {
int a = 10; // 栈 int b = 20; // 栈 // c : 栈
// Car对象(计数器==1) : 堆 Car *c = [[Car alloc] init];
}
// 经过上面的代码后, 栈里面的变量a\b\c都会被回收
// 但是堆里面的Car对象还会留在内存中, 因为它是计数器依然是1
return 0;
}

五、引用计数器

  • 系统是如何判断 什么时候需要回收一个对象所占用的内存?

    根据对象的引用计数器
5.1什么是引用计数器
  • 每个OC对象都有自己的引用计数器,由oc对象内部4个字节存储空间来存放

    它是一个整数

    从字面上, 可以理解为”对象被引用的次数”

    也可以理解为: 它表示有多少人正在用这个对象

    简单来说, 可以理解为: 引用计数器表示有多少人正在使用这个对象

5.2根据引用计数器来确定是否回收对象
  • 当没有任何人使用这个对象时, 系统才会回收这个对象, 也就是说:

    当对象的引用计数器为0时, 对象占用的内存就会被系统回收

    如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )

    所以我们以后就是通过操作引用计数器来管理内存

  • 任何一个对象, 刚生下来的时候, 引用计数器都为1

    当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1

5.3操作引用计数器

要想管理对象占用的内存, 就得学会操作对象的引用计数器

  • 引用计数器的常见操作

    给对象发送一条retain消息, 可以使引用计数器值+1(retain方法返回对象本身)

    给对象发送一条release消息, 可以使引用计数器值-1

    给对象发送retainCount消息, 可以获得当前的引用计数器值

需要注意的是: release并不代表销毁\回收对象, 仅仅是计数器-1

六、delloc方法

  • delloc方法调用

    当一个对象的引用计数器值为0时

    这个对象即将被销毁,其占用的内存被系统回收

    系统会自动给对象发送一条dealloc消息

    (因此, 从dealloc方法有没有被调用, 就可以判断出对象是否被销毁)

  • dealloc方法的重写

    一般会重写dealloc方法, 在这里释放相关资源, dealloc就是对象的遗言

    一旦重写了dealloc方法, 就必须调用[super dealloc],并且放在最后面调用

      - (void)dealloc
    {
    NSLog(@"Person ---- dealloc----"); // 必须调用, 必须放在最后面
    [super dealloc];
    }
  • 使用注意

    不能直接调用dealloc方法

    一旦对象被回收了, 它占用的内存就不再可用, 坚持使用会导致程序崩溃(野指针错误)

七、空指针、野指针

  • 僵尸对象

    已经被销毁的对象(不能再使用的对象)

  • 野指针

    指向僵尸对象(不可用内存/坏内存)的指针

    给野指针发消息会报EXC_BAD_ACCESS错误

  • 空指针

    没有指向存储空间的指针(里面存的是nil, 也就是0)

    给空指针发消息是没有任何反应的

  • 为了避免野指针错误的常见办法

    在对象被销毁之后, 将指向对象的指针变为空指针

八Xocde设置

要手动管理oc对象内存,需要在xcode中进行一下设置

  • 关闭ARC功能,才能手动调用retain、release等方法
  • 开启僵尸对象监控,默认情况下,Xcode是不会管僵尸对象的,使用一块被释放的内存也不会报错。为了方便调试,应该开启僵尸对象监控

九、内存管理原则

9.1 多对象内存管理

  • 单个对象的内存管理, 看起来非常简单

    如果对多个对象进行内存管理, 并且对象之间是有联系的, 那么管理就会变得比较复杂

    其实, 多个对象的管理思路 跟 很多游戏的房间管理差不多

    比如斗地主 \ QQ堂

  • 总的来说, 有这么几点管理规律

    只要还有人在用某个对象,那么这个对象就不会被回收

    只要你想用这个对象,就让对象的计数器+1

    当你不再使用这个对象时,就让对象的计数器-1

9.2 内存管理原则

  • 苹果官方规定的内存管理原则

    谁创建谁release : 如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease

    谁retain谁release :只要你调用了retain,就必须调用一次release

  • 总结一下就是

    有加就有减

    曾经让对象的计数器+1,就必须在最后让对象计数器-1

9.3 set方法的内存管理

  • set方法

      - (void)setCar:(Car *)car
    {
    if (car != _car)
    {
    // 对当前正在使用的车(旧车)做一次release
    [_car release];
    // 对新车做一次retain操作
    _car = [car retain];
    }
    }

9.4 dealloc方法的内存管理

  • dealloc方法

       - (void)dealloc
    {
    // 当人不在了,代表不用车了
    // 对车做一次release操作
    [_car release];
    [super dealloc];
    }

Objective-C —内存管理(上)的更多相关文章

  1. 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配

    垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

  2. C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

    C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...

  3. Objective C内存管理之理解autorelease------面试题

    Objective C内存管理之理解autorelease   Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的A ...

  4. 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法

    垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

  5. 垃圾回收GC:.Net自己主动内存管理 上(三)终结器

    垃圾回收GC:.Net自己主动内存管理 上(三)终结器 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主 ...

  6. Objective C 内存管理[转]

    1  配对原则 alloc – release new – release retain - release copy – release 2  new和alloc-init的区别 (1)区别只在于a ...

  7. objective C 内存管理及属性方法具体解释

    oc为每一个对象提供一个内部计数器.这个计数器跟踪对象的引用计数,当对象被创建或拷贝时.引用计数为1.每次保持对象时,调用retain接口.引用计数加1.假设不需要这个对象时调用release,引用计 ...

  8. Linux内存管理之地址映射

    写在前面:由于地址映射涉及到各种寄存器的设置访问,Linux对于不同体系结构处理器的地址映射采用不同的方法,例如对于i386及后来的32位的Intel的处理器在页式映射时采用的是2级页表映射,而对于I ...

  9. [基础] C++与JAVA的内存管理

    在内存管理上(总之一句话——以后C++工程,一定要用智能指针!) 1.同是new一个对象,C++一定得手动delete掉,而且得时刻记住能delete的最早时间(避免使用空指针).JAVA可以存活于作 ...

  10. GC与显式内存管理

    C++复兴的话题至今已被鼓吹两年有余,Herb Sutter和Bjarne Stroustrup等大牛们也为C++带来了大步伐的革新.然而,从这两年的效果而言,C++的复兴并没有发生.一方面随着世界经 ...

随机推荐

  1. USACO 2.1 Healthy Holsteins

    Healthy HolsteinsBurch & Kolstad Farmer John prides himself on having the healthiest dairy cows ...

  2. dubbo 解决既是消费者又是提供者 Duplicate application configs 的问题

    首先  有应用A  是 提供者 应用B 来实现既是消费者又是提供者 在应用 B 这边新建两个xml dubbo-consumer.xml  消费者 <!-- 自动扫描注解:通过dubbo实现 - ...

  3. BZOJ 2212线段树的合并

    借鉴(抄)了一下题解-- 线段树合并的裸题吧- //By SiriusRen #include <cstdio> #include <cstring> #include < ...

  4. dragView 屏幕拖拽并且弹出菜单的控件

    dragView 因项目新需求需要添加一个屏幕拖拽按钮可以弹出菜单的控件,因为不是我做的闲来无事写一个demo吧 可能存在一些小bug(毕竟就写了几个小时)兄弟姐妹们理解思路就行 具体的可以自己调试一 ...

  5. MFC框架下Opengl窗口闪屏问题解决方案

    转自https://blog.csdn.net/niusiqiang/article/details/43116153 虽然启用了双缓冲,但是仍然会出闪屏的情况,这是由于OpenGL自己有刷新背景的函 ...

  6. Vue学习之路第四篇:v-html指令

    上一篇我们讲解了两种方式,把Vue对象的数据展示在页面上: 1.插值表达式 2.v-text指令 但是如果我们展示的数据包含元素标签或者样式,我们想展示标签或样式所定义的属性作用,该怎么进行渲染,比如 ...

  7. 查看系统进程:ps、top

    1.ps命令:提供最近进程的快照.显示当前活跃进程的简要信息. 常见使用: (1)与grep命令配合查找是否有相应进程存活 ps -ef | grep ksmd ps -Af | grep ksmd ...

  8. Vue中如何在组件内部实现一个双向数据绑定?

    假设有一个输入框组件,用户输入时,同步父组件页面中的数据. 具体思路:父组件通过props传值给子组件,子组件通过 $emit 来通知父组件修改相应的props值,具体实现如下: import Vue ...

  9. Http请求和相应模式(B/S)(1)

    B/S模式 服务器端的接受数据 :浏览器端 表单格式 <form></form> GET:请求方式, /index.html  Web浏览器上的资源路径 uname=bjxt& ...

  10. mysql数据实时同步到Elasticsearch

    业务需要把mysql的数据实时同步到ES,实现低延迟的检索到ES中的数据或者进行其它数据分析处理.本文给出以同步mysql binlog的方式实时同步数据到ES的思路, 实践并验证该方式的可行性,以供 ...