OC-引用计数器,内存管理,野指针
总结
- 全局断点
- →-->+-->Add Exception Breakpoint
开启僵尸监听
- 打开Edit scheme -->Diagnostics-->Enable Zombie Object
retain 不仅仅会对计数器 + 1,而且还会返回当前对象
标号 | 标题 | 内容 |
---|---|---|
一 | 内存管理 | 内存管理的重要性/内存管理概念/堆和栈/内存管理原则/多对象内存管理/set方法内存管理/dealloc方法的内存管理 |
二 | 引用计数器 | 引用计数概念器/作用/操作 |
三 | dealloc | dealloc方法基本概念 |
四 | 野指针/空指针 | 僵尸对象概念/野指针概念/空指针概念 |
五 | Xcode设置 | 如何关闭ARC功能/如何开启僵尸对象监控 |
六 | Property修饰符 | 控制set方法的内存管理/控制需不需要生成set方法/多线程管理/控制set方法和get方法的名称 |
七 | @class | @class基本概念/应用场景/@class和#import区别 |
八 | 循环retain | 循环retian基本概念 |
一.内存管理
ARC: Automatic Reference Counting
什么是自动引用计数
- 不需要程序员管理内容,编译器会在适当的地方自动给我们添加release/retain等代码
- 注意点:
- OC中的ARC和Java中的垃圾回收机制不太一样,Java中的垃圾回收是系统干的,而OC中的ARC是编译器干的
- 只要创建一个对象默认引用计数器的值就是1
- MRC: Manual Reference Counting
- 什么是手动引用计数
- 所有对象的内容都需要我们手动管理,需要程序员自己编写release/retain等代码
- 内存管理的原则
- 有加有减
1.内存管理的重要性
移动设备的内存极其有限,每个app所能占用的内存是有限制的
下列行为都会增加一个app的内存占用
- 创建一个OC对象
- 定义一个变量
- 调用一个函数或者方法
如果app占用内存过大, 系统可能会强制关闭app, 造成闪退现象, 影响用户体验
2.什么是内存管理
如何回收那些不需要再使用的对象?
- 学会OC的内存管理
所谓内存管理, 就是对内存进行管理, 涉及的操作有:
- 分配内存 : 比如创建一个对象, 会增加内存占用
- 清除内存 : 比如销毁一个对象, 能减小内存占用
内存管理的管理范围
- 任何继承了NSObject的对象
- 对其他非对象类型无效(int、char、float、double、struct、enum等 )
只有OC对象才需要进行内存管理的本质原因
- OC对象存放于堆里面
- 非OC对象一般放在栈里面(栈内存会被系统自动回收)
3.堆和栈
栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出);
堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS(Operating System 操作系统)回收,分配方式类似于链表。
示例:
int main(int argc, const char * argv[])
{
@autoreleasepool {
int a = 10; // 栈
int b = 20; // 栈
// p : 栈
// Person对象(计数器==1) : 堆
Person *p = [[Person alloc] init];
}
// 经过上一行代码后, 栈里面的变量a\b\p都会被回收
// 但是堆里面的Person对象还会留在内存中,因为它是计数器依然是1
return 0;
}
4.内存管理原则
苹果官方规定的内存管理原则
谁创建谁release :
- 如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease
谁retain谁release:
- 只要你调用了retain,就必须调用一次release
总结一下就是
- 有加就有减
- 曾经让对象的计数器+1,就必须在最后让对象计数器-1
5.多对象内存管理
- 只要还有人在用某个对象,那么这个对象就不会被回收
- 只要你想用这个对象,就让对象的计数器+1
- 当你不再使用这个对象时,就让对象的计数器-1
6.set方法内存管理
- (1)retain需要使用的对象
- (2)release之前的对象
- (3)只有传入的对象和之前的不同才需要release和retain
- (void)setRoom:(Room *)room
{
// 避免过度释放
if (room != _room)
{
// 对当前正在使用的车(旧车)做一次release
[_room release];
// 对新车做一次retain操作
_room = [room retain];
}
}
7.dealloc方法的内存管理
- (void)dealloc
{
// 当人不在了,代表不用房间了
// 对房间做一次release操作
[_room release];
[super dealloc];
}
二.引用计数器
- 占4个字节
1.什么是引用计数器
系统是如何判断什么时候需要回收一个对象所占用的内存?
- 根据对象的引用计数器
什么是引用计数器
- 每个OC对象都有自己的引用计数器
- 它是一个整数
- 从字面上, 可以理解为”对象被引用的次数”
2.引用计数器的作用
简单来说, 可以理解为:
- 引用计数器表示有多少人正在使用这个对象
当没有任何人使用这个对象时,系统才会回收这个对象,也就是说
- 当对象的引用计数器为0时,对象占用的内存就会被系统回收
- 如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出)
任何一个刚创建的对象, 引用计数器都为1
- 当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1
3.引用计数器的操作
引用计数器的常见操作
- 给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身)
- 给对象发送一条release消息, 可以使引用计数器值-1
- 给对象发送retainCount消息,可以获得当前的引用计数器值
需要注意的是:release并不代表销毁\回收对象,仅仅是计数器-1
三.dealloc
1.dealloc方法基本概念
- 当一个对象的引用计数器值为0时,这个对象即将被销毁,其占用的内存被系统回收
对象即将被销毁时系统会自动给对象发送一条dealloc消息 (因此, 从dealloc方法有没有被调用,就可以判断出对象是否被销毁)
作用
- 用来判断对象是否被销毁
规律
- 当一个对象引用计数器 = 0时,该对象即将被销毁,就会调用dealloc
dealloc方法的重写
- 一般会重写dealloc方法,在这里释放相关资源
一旦重写了dealloc方法, 就必须调用[super dealloc](在MRC环境下),并且放在最后面调用
使用注意
- 不能直接调用dealloc方法
- 一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)
四.野指针/空指针
1.僵尸对象
- 已经被销毁的对象(不能再使用的对象)
2.野指针
- 指向僵尸对象(不可用内存)的指针
- 给野指针发消息会报EXC_BAD_ACCESS错误
3.空指针
- 没有指向存储空间的指针(里面存的是nil, 也就是0)
给空指针发消息是没有任何反应的
为了避免野指针错误的常见办法
- 在对象被销毁之后, 将指向对象的指针变为空指针
- 因为OC中给空指针发送消息不会报错
五.Xcode设置
1.如何关闭ARC功能
- 要想手动调用retain、release等方法 , 就必须关闭ARC功能
- 项目--> Bulid Setting / All --> 搜automatic-->将Objective-C Automatic Reference Counting 改成 No
2.如何开启僵尸对象监控
默认情况下,Xcode是不会管僵尸对象的,使用一块被释放的内存也不会报错。为了方便调试,应该开启僵尸对象监控
- Edit Scheme-->Diagnostics-->Objective-C后的Enable Zombile Objects 打√号
* 六.Property修饰符
1.控制set方法的内存管理
- retain : release旧值,retain新值(用于OC对象)
- retain会自动生成getter和setter方法内存管理的代码
- 相同的property修饰符不能同时使用
- retain会自动生成getter和setter方法内存管理的代码
- assign : 直接赋值,不做任何内存管理(默认,用于非OC对象类型)
- assign不会自动生成getter和setter方法内存管理的代码,仅仅只会生成普通的getter和setter方法(默认)
- copy : release旧值,copy新值(一般用于NSString *)
2.控制需不需要生成set方法
- readwrite :同时生成set方法和get方法(默认)
- readonly :只会生成get方法
3.多线程管理
- atomic:性能低(默认),一次只能通过一个人
- nonatomic:性能高,一次可以通过多个人(ios中多用此修饰符)
4.控制set方法和get方法的名称
- setter : 设置set方法的名称,一定有个冒号:
- getter : 设置get方法的名称
- 注意: 不同类型的参数可以组合在一起使用
七. @class
1.@class基本概念
作用
- 可以简单地引用一个类
简单使用
- @class Dog;
- 仅仅是告诉编译器:Dog是一个类;并不会包含Dog这个类的所有内容
具体使用
- 在.h文件中使用@class引用一个类
- 在.m文件中使用#import包含这个类的.h文件
2.@class其它应用场景
- 对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类
- 这种嵌套包含的代码编译会报错
#import "B.h"
@interface A : NSObject
{
B *_b;
}
@end
#import “A.h"
@interface B : NSObject
{
A *_a;
}
@end
- 当使用@class在两个类相互声明,就不会出现编译报错
@class B;
@interface A : NSObject
{
B *_b;
}
@end
@class A;
@interface B : NSObject
{
A *_a;
}
@end
3.@class和#import区别
作用上的区别
- #import会包含引用类的所有信息(内容),包括引用类的变量和方法
- @class仅仅是告诉编译器有这么一个类,具体这个类里有什么信息,完全不知
效率上的区别
- 如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,编译效率非常低
- 相对来讲,使用@class方式就不会出现这种问题了
八. 循环retain
1.循环retian基本概念
循环retain的场景
- 比如A对象retain了B对象,B对象retain了A对象
循环retain的弊端
- 这样会导致A对象和B对象永远无法释放
循环retain的解决方案
- 当两端互相引用时,应该一端用retain、一端用assign
OC-引用计数器,内存管理,野指针的更多相关文章
- OC语法6——内存管理之引用计数器(retain,release)
OC内存管理: 一.引用计数器: Java有垃圾回收机制(Garbage Collection,GC).也就是说当我们创建对象后,不需要考虑回收内存的事,Java的垃圾回收机制会自动销毁该对象,回收它 ...
- OC开发系列-内存管理
概述 移动设备的内存极其有限,每个app所有占用的内存是有限的.当app所占用的内存比较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. 任何集成了NSObject的对象都需要手动进行 ...
- OC学习10——内存管理
1.对于面向对象的语言,程序需要不断地创建对象.这些对象都是保存在堆内存中,而我们的指针变量中保存的是这些对象在堆内存中的地址,当该对象使用结束之后,指针变量指向其他对象或者指向nil时,这个对象将称 ...
- C#高级编程9 第14章 内存管理和指针
C#高级编程9 内存管理和指针 后台内存管理 1) 值数据类型 在处理器的虚拟内存中有一个区域,称为栈,栈存储变量的浅副本数据,通过进入变量的作用域划分区域,通过离开变量的作用域释放. 栈的指针指向栈 ...
- OC中的内存管理
一. 基本原理 1. 什么是内存管理 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间.比如回收一些不需 ...
- oc对象的内存管理
oc没有java的垃圾回收机制,所以对象的内存释放很重要,基本数据类型,我们不用理会,编译器会处理: oc的每个对象内部都由一个计数器,用来记录当前有几个指针在指向该对象:当计数器为0时该对象会从内存 ...
- OC修饰词 - 内存管理
<招聘一个靠谱的 iOS>—参考答案(上) 说明:面试题来源是微博@我就叫Sunny怎么了的这篇博文:<招聘一个靠谱的 iOS>,其中共55题,除第一题为纠错题外,其他54道均 ...
- C语言回顾-内存管理和指针函数
1.fgets()函数 该函数是一个文件操作相关的函数 暂时使用这个函数可以从键盘上接收一个字符串,保存到数组中 char str[50]; 1)scanf("%s",str);/ ...
- iOS中引用计数内存管理机制分析
在 iOS 中引用计数是内存的管理方式,虽然在 iOS5 版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于 debug 程序. 操作系统的内存管理分成堆和 ...
- 初步swift语言学习笔记6(ARC-自己主动引用计数,内存管理)
笔者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/31824179 转载请注明出处 假设认为文章对你有所帮助.请通过留言 ...
随机推荐
- ICMP 协议仿真及ping命令用途
1.实验目的 加深对 IPv4 协议首部各定义域的理解,掌握路由表的结构和基本配置命令,熟悉 ICMP 的调试操作. 2.实验原理 IPv4 协议定义,网络层协议的相关 RFC 定义和描述. 3.实验 ...
- vscode + vim 全键盘操作高效搭配方案
基础知识 vscode-vim vscode-vim是一款vim模拟器,它将vim的大部分功能都集成在了vscode中,你可以将它理解为一个嵌套在vscode中的vim. 由于该vim是被模拟的的非真 ...
- Django 中间件 详细总结
一.什么是中间件 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨慎实用,用不好会影 ...
- webpack 打包样式资源
webpack 打包样式资源 webpack.config.js配置文件内容为: // 用来拼接绝对路径的方法 const {resolve} = require('path') module.exp ...
- 将python代码转化为c语言代码,提高运行效率
将python代码转化为c语言代码,提高运行效率 首先,需要安装cpython库: pip install cython 安装完成之后,写一段简单的代码,例如下面这个利用递归求斐波那契数列的函数,然后 ...
- Vue3+Vue-cli4项目中使用腾讯滑块验证码
Vue3+Vue-cli4项目中使用腾讯滑块验证码 简介: 滑块验证码相比于传统的图片验证码具有以下优点: 验证码的具体验证不需要服务端去验证,服务端只需要核验验证结果即可. 验证码的实现不需要我们去 ...
- Could not set property 'id' of 'class com.xxx.xxEntity'
使用mybatisplus的save功能时,系统报错如下: Could not set property 'id' of 'class com.xxx.xxEntity' with value '13 ...
- Go语言核心36讲(Go语言实战与应用五)--学习笔记
27 | 条件变量sync.Cond (上) 前导内容:条件变量与互斥锁 我们常常会把条件变量这个同步工具拿来与互斥锁一起讨论.实际上,条件变量是基于互斥锁的,它必须有互斥锁的支撑才能发挥作用. 条件 ...
- vue.js学习与实战笔记(1)
公司需要开发一个小型官网,个人决定放弃angular2,使用vue来进行开发,由于是培训出生,思想一时难以转变,所以只能从零开始,下面奉上学习笔记 vue.js主要参考官网进行学习与开发 由于vue不 ...
- LeetCode->链表反转
这是一个很基础的题目.今天处理了一下,不论是以双指针迭代.递归等方法,都能处理,但是也使这个题目更为典型. 剑指 Offer 24. 反转链表 - 力扣(LeetCode) (leetcode-cn. ...