内存管理初级
来源:互联网 发布:hmcl启动器 linux 编辑:程序博客网 时间:2024/06/05 16:29
复习C语言中的内存:
int *p = malloc(8); —>堆内存
free(p);
free(p); —>过度释放
- 内存溢出: 内存不释放
- 野指针: free之后还可以用p找到那块内存, 因为是标记删除; 但内存中内容不能保证还是原来的, 因为所有权已还给系统
野指针异常是程序crash主要原因
将ARC改为MRC:
- ARC Automatic Reference Counting 自动引用计数
- MRC Manual Reference Counting 手动引用计数
- 关闭ARC就是MRC
- ARC是基于MRC的
内存管理:
1. - retainCount: 打印当前对象的引用计数, 结果只能作为一个参考
2. + alloc: 开辟内存空间,让被开辟的内存空间引用计数变为1, 这是由0到1的过程
Person*person1 = [[Personalloc]init];
此时 person1 引用计数由0变为1
NSLog(@"%lu", [person1retainCount]);
打印结果: 1
3. - retain: 引用计数+1
[person1retain];
[person1retain];
person1 引用计数两次 +1
NSLog(@"%lu", [person1retainCount]);
打印结果: 3
4. - release: 引用计数-1, 而不是释放
[person1release];
person1引用计数 -1
NSLog(@"%lu", [person1retainCount]);
打印结果: 2
[person1release];
NSLog(@"%lu", [person1retainCount]);
打印结果: 1
[person1 release];
NSLog(@"%lu", [person1retainCount]);
打印结果: 1(*为何是1而不是0?)
[person1release];
过多的释放,会导致crash
内存的所有权:
所有权是管理内存的根本性的问题, 一个指针能不能对内存进行release, 就看有没有所有权.
只有开辟空间的对象才拥有内存的所有权.
5. - autorelease: 出自动释放池 (@autoreleasepool {}) 时-1
Person*person2 = [[Personalloc]init];
@autoreleasepool{
[person2 retain];
[person2retain];
[person2release];
[person2 autorelease];
[person2autorelease];
// [person2 autorelease]; —>同样会造成过度释放
NSLog(@"%lu", [person2retainCount]);
打印结果: 2
} —> 在出释放池,运行释放池后第一个语句之前会执行dealloc
NSLog(@"%lu", [person2retainCount]);
打印结果: 1
6. - dealloc: 释放内存, 当对象的引用计数变为0的时候, 系统会自动调用dealloc方法, 可以重写父类的dealloc方法, 重写时不用声明,不能手动调用.
在类中重写dealloc方法:
- (void)dealloc{
[_namerelease]; —> 将由成员变量指向的内存空间的引用计数-1. 基本数据类型的成员变量不需要release, 因为在栈区, 由系统自动管理
[_sexrelease];
[superdealloc];
}
调用父类的dealloc方法,释放公共部分的属性和成员变量,[superdealloc]; 作为方法的最后一句.
7. - copy: 会开辟一段内存空间, 和原来大小一致, 存储内容一致, 会保持原来的引用计数不变,新的内存引用计数变为1. 遵循NSCopying协议才能使用copy.
想要使自己创建的Person类使用copy方法:
1. 签订NSCopying协议: @interface Person : NSObject<NSCopying>
2. 在.h文件中实现NSCopying协议中声明的方法: - (id)copyWithZone:(NSZone*)zone;
- (id)copyWithZone:(NSZone*)zone{
NSZone, 内存池, 里面的内存都是没用过的
Person *p = [[PersonallocWithZone:zone]init];
使用拷贝区zone, 创建一个新的对象, 相当于开辟空间, 并初始化
p.name= self.name;
p.sex =self.sex;
把对象自己的属性内容给新的对象拷贝一份
return p;
}
3. 使用copy方法: Person *person8 = [person7 copy];
*关于release方法的实现:
系统不让重写release方法, 此处仅为演示:
//- (void)release{
//
//
// if (self.retainCount == 1) {
//// self.retainCount—; —>当引用计数为1的时候调用release,目的为将内存还给系统,所以没有必要再-1了,直接释放内存即可
// [self dealloc];
// }else{
// self.retainCount--;
// }
// }else{
// self.retainCount--;
// }
//}
内存管理的原则:
- 当看到alloc, retain, copy时, 要写release, 要保证引用计数的加减平衡
- 如果但不到, 则不管
说明:
引用计数的变化针对的是内存空间,而不是指针变量.
Person *person001 = [[Personalloc] init];
NSLog(@"%lu", [person001retainCount]); —> 打印结果:1
[person001retain];
[person001retain];
NSLog(@"%lu", [person001retainCount]); —> 打印结果:3
Person*person002 = person001;
NSLog(@"%lu", [person002retainCount]);—> 打印结果: 3
此时person002 与 person001 指的是同一块内存空间
[person002 release];
NSLog(@"%lu", [person001retainCount]); —> 打印结果: 2
当对person2进行release操作时, 使用person001调用retainCount打印出的结果同样会-1
数组的内存管理:
Person*person3 = [[Personalloc]init];
NSMutableArray*arr = [NSMutableArrayarray];
[arr addObject:person3];
NSLog(@"%lu, %lu", [arrretainCount], [person3retainCount]);
打印结果: 1, 2
[arr removeObject:person3];
NSLog(@"%lu", [person3retainCount]);
打印结果: 1
被加入到数组中的元素会被retain一次.
当元素被移除的时候,元素会被release一次.
0 0
- 内存管理初级
- OC 内存管理(初级)
- 内存管理初级
- OC内存管理初级
- 内存管理初级
- OC 内存管理初级
- 内存管理初级
- 09 内存管理初级
- 内存管理初级
- OC__内存管理初级
- OC内存管理初级
- 9、内存管理初级
- 内存管理初级
- OC内存管理初级演练
- iOS中内存初级管理
- oc的内存管理初级
- C语言内存管理(初级)----动态数组
- C语言内存管理(初级)----链表
- [每天一个知识点]32-职业生涯-不值得定律
- 2014——年终总结
- 初识依赖注入
- C++ Primer 第7章 学习笔记 思维导图
- the max common divisor
- 内存管理初级
- SimpleCursorAdapter() 是 SimpleCursorAdapter 类的构造函数。
- 我的时间管理回顾——磨刀不误砍柴工
- 内存管理高级
- Spring AOP注解通过@Autowired,@Resource,@Qualifier,@PostConstruct,@PreDestroy注入属性的配置文件详解
- Recover Binary Search Tree
- 盛大员工积分体系的坍塌:为什么“打怪刷分”在现实里行不通
- 常见浏览器兼容问题及相关解决方法(chrome/IE/firefox)
- HHD Software Hex Editor Neo Ultimate Edition v6 10 02 5330-CRD