教育行业A股IPO第一股(股票代码 003032)

全国咨询/投诉热线:400-618-4000

iOS面试之内存管理篇!

更新时间:2016年03月04日17时55分 来源:传智播客 浏览次数:

  内存管理(★★★)

  一、怎么保证多人开发进行内存泄露的检查。


  • 使用Analyze进行代码的静态分析

  • 为避免不必要的麻烦, 多人开发时尽量使用ARC


  二、非自动内存管理情况下怎么做单例模式。


  创建单例设计模式的基本步骤:

  >声明一个单件对象的静态实例,并初始化为nil;

  >创建一个类的类工厂方法,当且仅当这个类的实例为nil时生成一个该类的实例;

  >实现NScopying协议, 覆盖allocWithZone:方法,确保用户在直接分配和初始化对象时,不会产 生另一个对象;

  >覆盖release、autorelease、retain、retainCount方法, 以此确保单例的状态;

  >在多线程的环境中,注意使用@synchronized关键字或GCD,确保静态实例被正确的创建和初始化。


  三、对于类方法(静态方法)默认是autorelease的。所有类方法都会这样吗?


  1> 系统自带的绝大数类方法返回的对象,都是经过autorelease的。


  四、block在ARC中和MRC中的用法有什么区别,需要注意什么?


  1.对于没有引用外部变量的Block,无论在ARC还是非ARC下,类型都是__NSGlobalBlock__,这种类型的block可以理解成一种全局的block,不需要考虑作用域问题。同时,对他进行Copy或者Retain操作也是无效的;

  2.应注意避免循环引用。


  五、什么情况下会发生内存泄漏和内存溢出?


  当程序在申请内存后,无法释放已申请的内存空间(例如一个对象或者变量使用完成后没有释放,这个对象一直占用着内存),一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存泄露会最终会导致内存溢出!

  当程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。


  六、[NSArrayarrayWithobject:] 这个方法添加对象后,需要对这个数组做释放操作吗?

  不需要 这个对象被放到自动释放池中。


  七、Json数据的解析?


  • JSON解析的方案


  1、SBJson
;

  2、JSONkit
;

  3、NSJSONSerialization
。


  八、自动释放池底层怎么实现?


  自动释放池以栈的形式实现:当你创建一个新的自动释放池时,它将被添加到栈顶。当一个对象收到发送autorelease消息时,它被添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,它们从栈中被删除, 并且会给池子里面所有的对象都会做一次release操作。


  九、自动释放池是什么,如何工作?


  当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。

  1. ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到release和autorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁。

  2. NSAutoreleasePool 就是用来做引用计数的管理工作的,这个东西一般不用你管的。

  3. autorelease和release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一。


  十、Objective-C如何对内存管理的,说说你的看法和解决方法?


  Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。

  1、(Garbage Collection)自动内存计数:这种方式和java类似,在你的程序的执行过程中。始终有一个高人在背后准确地帮你收拾垃圾,你不用考虑它什么时候开始工作,怎样工作。你只需要明白,我申请了一段内存空间,当我不再使用从而这段内存成为垃圾的时候,我就彻底的把它忘记掉,反正那个高人会帮我收拾垃圾。遗憾的是,那个高人需要消耗一定的资源,在携带设备里面,资源是紧俏商品所以iPhone不支持这个功能。所以“Garbage Collection”不是本入门指南的范围,对“GarbageCollection”内部机制感兴趣的同学可以参考一些其他的资料,不过说老实话 “GarbageCollection”不大适合适初学者研究。

  解决:通过alloc– initial方式创建的, 创建后引用计数+1, 此后每retain一次引用计数+1,那么在程序中做相应次数的release就好了。

  2、(Reference Counted)手动内存计数:就是说,从一段内存被申请之后,就存在一个变量用于保存这段内存被使用的次数,我们暂时把它称为计数器,当计数器变为0的时候,那么就是释放这段内存的时候。比如说,当在程序A里面一段内存被成功申请完成之后,那么这个计数器就从0变成1(我们把这个过程叫做alloc),然后程序B也需要使用这个内存,那么计数器就从1变成了2(我们把这个过程叫做retain)。紧接着程序A不再需要这段内存了,那么程序A就把这个计数器减1(我们把这个过程叫做release);程序B也不再需要这段内存的时候,那么也把计数器减1(这个过程还是release)。当系统(也就是 Foundation)发现这个计数器变成了0,那么就会调用内存回收程序把这段内存回收(我们把这个过程叫做dealloc)。顺便提一句,如果没有 Foundation,那么维护计数器,释放内存等等工作需要你手工来完成。

  解决:一般是由类的静态方法创建的, 函数名中不会出现alloc或init字样, 如[NSStringstring]和[NSArray arrayWithObject:], 创建后引用计数+0,在函数出栈后释放, 即相当于一个栈上的局部变量. 当然也可以通过retain延长对象的生存期。

  3、(NSAutoRealeasePool)内存池:可以通过创建和释放内存池控制内存申请和回收的时机。

  解决:是由autorelease加入系统内存池,内存池是可以嵌套的, 每个内存池都需要有一个创建释放对, 就像main函数中写的一样. 使用也很简单,比如[[[NSString alloc]initialWithFormat”Hey you!”] autorelease], 即将一个NSString对象加入到最内层的系统内存池, 当我们释放这个内存池时, 其中的对象都会被释放。


  十一、需要在手动管理内存分配和释放的Xcode项目中引入和编译用ARC风格编写的文件,需要在文件的CompilerFlags上添加参数。



0 分享到:
和我们在线交谈!