Objective-C_内存管理

内存管理

MRC:

对象的生命周期:

1.通过alloc,new和copy等方式将对象产生出来,这个时期是对象的产生时期

2.初始化后的对象可以接收消息和执行动作,也可以和其它对象进行信息交换和相互调用,这个时期是对象的生存时期

3.对象完成其使命后,我们将其从内存中移除,这个时期是对象的死亡和销毁时期

引用计数器:

1.当对象刚刚被创建其初始值为1

2.当有某段代码需要访问一个对象时,会将该对象的引用计数器加1(通过retain来实现)

3.当某段代码结束访问一个对象时,会将该对象的引用计数器减1(通过release来实现)

4.当某段代码结束访问一个对象时,如果采用了autorelease方式,在当前自动释放池结尾会将该对象引用计数器减1

5.当对象的引用计数器为0时,代表所有其它代码均不再需要访问该对象,该对象会被自动销毁,其占用的内存空间会被回收

示例:

#import <Foundation/Foundation.h>

#import "Student.h"

#import "Dog.h"

int main(int argc, const char * argv[]) {

@autoreleasepool {

Dog *dog = [[Dog alloc]init];

NSLog(@"dog.retainCount:%ld",dog.retainCount);//为1

[dog release];

   NSLog(@"dog.retainCount:%ld",dog.retainCount);

[dog bark];

//注意:写完之后多运行几次,看看会造成什么效果,dog虽然是release了,但是偶尔还能调用dog的方法,这是因为编译器有时候跑得很快,还没来得及释放,就已经跑完所有代码了,事实上dog已经释放了

}

return 0;

}

运行结果:

2015-09-17 16:39:37.633 OC_5.0_MemeryManage[853:43528] dog.retainCount:1

2015-09-17 16:39:37.635 OC_5.0_MemeryManage[853:43528] dog 已经被释放了

2015-09-17 16:39:37.635 OC_5.0_MemeryManage[853:43528] dog.retainCount:1

2015-09-17 16:39:37.635 OC_5.0_MemeryManage[853:43528] 汪汪汪汪。。。。

上面的例子,第二次retainCount,按原理应该为0,但却不是。苹果公司的文档关于此问题的解释是:在调试程序的时候观察对象的retainCount值是没有意义的,因为系统框架中的对象可能还会retain该对象以便保持对其引用,同时自动释放池也可能会持有该对象,因此不能仅凭retainCount来判断对象的引用计数。所以说retainCount只是一个参考值

对象所有权:

内存管理模型是基于对象所有权的。一个对象可能有一个或多个所有者。只要对象有走过一个所有者,则该对象会一直存在。

为了要搞清什么时候拥有对象,什么时候不再拥有,有如下的原则:

1.谁创建谁拥有,可以通过alloc,new,copy,mutableCopy等方法创建的对象

2.可以通过retain来获取对象的所有权

有两种情况需要使用retain:(1)在setter方法和init方法里,当你想要将一个对象作为属性来使用

             (2)为了避免其它操作使对象变成无效的对象

3.如果不再需要一个对象,必须释放拥有对象的所有权

4.如果不拥有一个对象,不能释放该对象的所有权

集合与对象所有权

当我们将一个对象加入到集合(如数组、字典、set集合)中时,集合会拥有该对象的所有权;当集合移除该对象,或者集合对象本身被清理,集合会放弃对象的所有权。

为了确保内存管理不出错,总结了以下几点原则

1.当使用new,alloc或copy方法创建一个对象时,该对象引用计数器为1.如果不需要使用该对象,可以使用release或autorelease方法,在其使用完毕将其销毁

2.如果通过其他方法获取一个对象,则可以假设这个对象,引用计数为1,并且被设置为autorelease,不需要对该对象进行清理,如果确实需要retain这个对象,则需要使用完毕后release

3.如果retain了某个对象,需要release或autorelease该对象,保持retain和release使用次数相等

总得来说就是,谁创建 ,谁释放。

在dealloc中释放对象的所有权

在使用dealloc中要注意:

1.绝对不要直接调用另一个对象的dealloc方法

2.在dealloc方法实现的最后要调用父类的dealloc方法

3.当应用结束时,系统未必会调用对象的dealloc方法

采用弱引用避免循环retain

例子:

教师类中有学生

#import <Foundation/Foundation.h>

@class Student;

@interface Teacher : NSObject

@property(nonatomic,retain)Student *student;

@end

学生类中有教师

#import <Foundation/Foundation.h>

@class Teacher;

@interface Student : NSObject

@property(nonatomic,retain)Teacher *teacher;

@end

相互retain强强引用,就会造成,你中有我,我中有你,要释放student,那么就要释放teacher,要释放teacher,那么就要释放student

大家都在等待对方释放,循环retain

解决办法就是其中一个使用弱引用assign;

ARC

ARC技术实际也是运用引用计数,只是程序员不用再去手动引用计数,相当于身边多了一个内存管理高手帮助我们去管理内存

ARC技术引入了一些新的规则:

1.不能显式调用,dealloc语句,或实现或者调用retain,release,retainCount和autorelease等方法

2.不能调用@selector(retain)、@selector(release)等等

3.可以实现dealloc,但方法中不用释放实例变量,也不能调用[super dealloc].

4.不能使用NSAutoreleasePool对象,用@autorelesepool块来代替

5.不能用开头为new的名称来定义一个属性,除非定义一个别的getter名称,如下:

//以下代码不能正常工作:

@property NSString *newTitle;

//这样可以

@property (getter = theNewTitle) NSString *newTitle;

浅拷贝与深拷贝

copy:

1.copy对于不可变对象相当于retain,

2.对于可变对象,是深拷贝(复制了一个新的内存空间,新对象与旧对象不是同一个)

3.但是深拷贝不一定是完全拷贝。对象里面复合的对象有可能还是浅拷贝,甚至是没有拷贝

mutableCopy:

不可变对象经过mutableCopy之后,发生了深拷贝,而且返回一个可变对象

时间: 2024-10-13 03:58:26

Objective-C_内存管理的相关文章

Objective C 内存管理[转]

1  配对原则 alloc – release new – release retain - release copy – release 2  new和alloc-init的区别 (1)区别只在于alloc分配内存的时候使用了zone. 这个zone是个什么呢? 它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度. (2)为什么不推荐使用new 因为若用了new,则初始化方法只能是init.这样,假如你想调用initWithFram

objective C 内存管理及属性方法详解

oc为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc 当对象包含其他对象时,就得在dealloc中自己释放他们 NSObject是IOS所有类的基类 有两个基本函数,alloc和dealloc alloc类似于C++的new,dealloc类似于delete 当对象的re

iOS核心语言Objective C语言 —— 内存管理

本分享是面向有意向从事iOS开发的伙伴以及苹果产品的发烧友们,或者已经从事了iOS的开发者,想进一步提升者.如果您对iOS开发有极高的兴趣,可以与我一起探讨iOS开发,一起学习,共同进步.如果您是零基础,建议您先翻阅我之前分享的iOS开发分分钟搞定C语言系列,然后在开始Objective C语言的学习,如果您遇到问题也可以与我探讨,另外将无偿分享自己整理出来的大概400G iOS学习视频及学习资料,都是干货哦!可以新浪微博私信?关注极客James,期待与您的共同学习和探讨!!由于时间有限,每天在

Objective -C Memory Management 内存管理 第一部分

Objective -C Memory Management??内存管理??第一部分 Memory management is part of a more general problem in programming called resource management. 内存管理是资源管理的一部分. Every computer system has finite resources for your program to use. These include memory, open fi

Objective-C(内存管理)

引用计数器 每个OC对象都有一个占4个字节存储空间的引用计数器 当使用或创建一个对象时,新对象的引用计数器默认是1 retain:可以使引用计数器+1 release:可以是引用计数器-1 retainCount:获得当前的引用计数器的值 当对象被销毁时,会重写dealloc方法 -(void)dealloc { // 这句必须放在最后面 [super dealloc]; } 僵尸对象:所占内存已经被回收的对象,僵尸对象不能再使用 野指针:指向僵尸对象(不可用的内存)的指针 错误:EXC_BAD

IOS学习笔记3—Objective C—简单的内存管理

今天简述一下简单的内存管理,在IOS5.0以后Apple增加了ARC机制(Automatic Reference Counting),给开发人员带来了不少的方便,但是为了能更好的理解IOS内存管理机制,还是需要对其比较了解. 1.在OC中,每个对象都有一个保留计数,创建时每个对象都有一个初始值为1的保留计数,释放时,保留计数都为0 2.创建自动释放的对象 要求以一个方法创建对象时,以自动释放的形式返回该对象是一个很好的编程实践 +(Car *)car { Car *myCar = [[Car a

iOSDay17之内存管理

1.内存管理的方式 1> iOS应用程序出现Crash(闪退),90%的原因是因为内存问题. 2> 内存问题 野指针异常:访问没有所有权的内存,如果想要安全的访问,必须确保空间还在 内存泄露:空间使用完之后没有及时释放 过度释放:对同一块存储空间释放多次,立刻crash 内存溢出:所有存储空间被占用 3> 管理内存的三种方式 垃圾回收机制:程序员只需要开辟存储空间,系统会自动回收内存.java采用的该机制 MRC:手动引用计数机制,由开发人员开辟空间,手动添加影响引用计数增加或减少的方法

Objective-C----MRC内存管理 、 自动释放池 、 面向对象三大特性及封装 、 继承 、 组合与聚合

1 MRC练习 1.1 问题 引用计数是Objective-C语言采用的一种内存管理技术,当一个对象被创建在堆上后,该对象的引用计数就自动设置为1,如果在其它对象中的对象成员需要持有这个对象时,则该对象的引用计数被加上1,此时如果该对象被释放,内存管理程序将首先把该对象的引用计数减1,然后判断该对象的引用计数是否为0,由于其它对象在持有该对象时将引用计数加了1,所以此时该对象的引用计数减1后不为0,则内存管理程序将不会释放该对象.直到持有该对象的其它对象也被释放时,该对象的引用计数再次减1,变为

&lt;Linux内核源码&gt;内存管理模型

题外语:本人对linux内核的了解尚浅,如果有差池欢迎指正,也欢迎提问交流! 首先要理解一下每一个进程是如何维护自己独立的寻址空间的,我的电脑里呢是8G内存空间.了解过的朋友应该都知道这是虚拟内存技术解决的这个问题,然而再linux中具体是怎样的模型解决的操作系统的这个设计需求的呢,让我们从linux源码的片段开始看吧!(以下内核源码均来自fedora21 64位系统的fc-3.19.3版本内核) <include/linux/mm_type.h>中对于物理页面的定义struct page,也

objective-c(内存管理)

本文主要记录objective-c 内存管理的知识点: 1.objective-c的对象都是分配内存在堆上,与C的mallock和C++的new类似,只有int等系统变量分配内存在栈上: 2.objective-c没有java这般复杂的垃圾回收机制,它用的是引用计数,可以理解为创建该对象后,指向该对象首地址的指针是否在其他地方被引用,若增加引用则引用数加一,反之减一,当引用数为零时系统清除该变量.内部应该是堆上分配的地址重新设置为有效,也就是说可以再次分配给其他对象,存储该对象首地址的指针清除,