1.
什么情况下会发生内存泄漏和内存溢出?
答:当程序在申请内存后,无法释放已申请的内存空间(例如一个对象或者变量使用完成后没有释放,这个对象一直占用着内存),一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存泄露会最终会导致内存溢出!
当程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。
2.
自动释放池底层怎么实现
答:自动释放池以栈的形式实现:当你创建一个新的自动释放池时,它将被添加到栈顶。当一个对象收到发送autorelease消息时,它被添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,它们从栈中被删除, 并且会给池子里面所有的对象都会做一次release操作.
3
简述OC中 内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是 release,为什 么?readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak属性的作 用?
答:OC中内存管理机制应该就是引用计数的增减吧,retainCount为0时释放该内存。
retain对应的是release,内存的释放用release。
alloc对应的是dealloc,内存的销毁用dealloc。
readwrite此标记说明属性会被当成读写的,这也是默认属性。
readonly此标记说明属性只可以读,也就是不能设置,可以获取。
assign不会使引用计数加1,也就是直接赋值。
retain会使引用计数加1。
copy建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝。
nonatomic:非原子性访问,多线程并发访问会提高性能。
atomic:原子性访问。
strong:打开ARC时才会使用,相当于retain。
weak:打开ARC时才会使用,相当于assign,可以把对应的指针变量置为nil。
4.
堆栈的区别:
答:(1)管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生 memory leak。
(2)申请大小:能从栈获得的空间较小,堆是向高地址扩展的数据结构,是不连续的内存区域。堆的大小受限于计算机系统中 有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
(3)碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。 对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块 从栈中间弹出
(4)分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成 的,比如局部变量的分配。动态分配由 alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器 进行释放,无需我们手工实现。
(5)分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈 都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。
5.
分别描述内存管理要点、autorelease、release、NSAutoreleasePool?并说明autorelease是什 么时候被release的?简述什么时候由你负责释放对象,什么时候不由你释放?
[NSAutoreleasePool release]和[NSAutoreleasePool drain]有什么区别?
内存管理要点:
Objective-C 使用引用计数机制(retainCount)来管理内存。内存每被引用一次,该内存的引用计数+1,每被释放一次引 用计数-1。当引用计数 = 0 的时候,调用该对象的 dealloc 方法,来彻底从内存中删除该对象。 alloc,allocWithZone,new(带初始化)时:该对象引用计数 +1;
retain:手动为该对象引用计数 +1;copy:对象引用计数 +1;
mutableCopy:生成一个新对象,新对象引用计数为 1; release:手动为该对象引用计数 -1; autorelease:把该对象放入自动释放池,当自动释放池释放时,其内的对象引用计数 -1。 NSAutoreleasePool: NSAutoreleasePool是通过接收对象向它发送的autorelease消息,记录该对象的release消息,当自动释放池被销毁 时,会自动向池中的对象发送release消息。 autorelease 是在自动释放池被销毁,向池中的对象发送release 只能释放自己拥有的对象, 区别是:在引用计数环境下(在不使用ARC情况下),两者基本一样,在GC环境下,release 是一个no-op(无效操 作),所以无论是不是gc都使用drain
6.
IPhone OS有没有垃圾回收?autorelease 和垃圾回收制(gc)有什么关系?
答:没有。autorelease只是延迟释放,gc是每隔一段时间询问程序,看是否有无指针指向的对象,若有,就将它回收。他们 两者没有什么关系。
7.
为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的? 会引起循环引用----若是retain,在alloc一次之后,若release一次,会导致内存泄漏,若release两次会导致两个 对象的dealloc嵌套执行,结果就是都没有执行成功,最后崩溃! 所有的引用计数系统,都存在循环应用的问题。
答:例如下面的引用关系:
* 对象a创建并引用到了对象b.
* 对象b创建并引用到了对象c.
* 对象c创建并引用到了对象b.
这时候b和c的引用计数分别是2和1。 当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。 b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。 这种情况,必须打断循环引用,通过其他规则来维护引用关系。我们常见的delegate往往是assign方式的属性而不是 retain方式 的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。 如果一个UITableViewController 对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的 delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用 delegate模式时,也要注意这点。
8.
深拷贝和浅拷贝的理解?
答:对一个实例进行深拷贝时当前类需要实现NSCopying协议。 浅拷贝是复制出来一个跟原对象是同一地址的对象,而深拷贝则是复制出来一个跟源对象不同地址的对象,改变原对象,对新对象没有影响。
9.
什么是安全释放?
答:把对象指针置为nil,再对其释放。
10.
谈谈你对iOS内存管理的理解
答:在Objective-C2.0之后引入了垃圾回收机制(GC),但是只是在MAC OS X系统下,iOS下没有垃圾回收。
Objective-C采用了引用计数的机制来管理对象,引用计数的值表示几个对象在使用它,当对象的引用计数为0的时候,系统负责对象的销毁。可以表述为:1、自己生产的对象(你可以通过alloc(allocWithZone)、new、copy、mutableCopy或者是以这几个单词开头的方法创建对象),自己持有;2、非自己生产的对象,自己也能持有(使用retain);3、不需要持有的对象,自己负责释放(release、autorelease);4、非自己持有的对象,无法释放。内存管理的方式有两种:MRC(手动管理引用计数)和ARC(自动管理引用计数:编译器会在适当的地方插入retain、release、autorelease)。
11.
简述OC中内存管理机制
答:1.内存管理分为ARC和MRC两大方面,采用引用计数机制管理内存
2.MRC方面分为,创造一个对象时会采用allco方法,这时这对象的引用计数为1,我们称为这个对象的对象所有权为1,增加一个对象引用计数的方法还有retain,copy,add等于减少一个对象引用计数的方法为release和autorelease,当一个对象的引用计数减少的方法,使其保持平衡。当一个对象的引用计数为1的时候,我们在调用release或者autorelease的时候,系统会自动调用dealloc方法,释放对象所占资源。
3.ARC方面,其采用的也是引用计数机制,其原理和MRC一样,只不过把MRC中我们自己管理内存的方式交给了编译器来管理,仍然需要管理内存。
4.属性修饰词方面:其属性修饰词中和内存有关的,retain,assign,copy,weak,strong其中retain,会使其对象的引用计数加1,assign只是简单的赋值,不会引起引用计数增加,copy分为两种情况:1.深copy会对和浅copy相当于retain,深copy会对copy出来的对象从新开辟一块内存空间,需要对copy出来的对象单独做内存管理。而weak是在ARC中使用的修饰词,其作用相当于assign,但是它有一点比较好的是assign修饰对象为空时,其指针指向nil,防止野指针的出现,strong相当于retain。