iphone(object-c) 内存管理(3) 有效的内存管理 后半部分

现在搞iphone开发,一直不是很懂object-c的内存管理机制,看到apple的官方文档写的不错而又没有找到翻译的文章。于是自己在学习它的过程中就顺便把它翻译了,自己的英语不是太好,文字组织能力那就更菜了,读的蹩脚之处还望大家指出,我好在以后的翻译过程中好好改正。第一次翻译,欢迎拍砖,可不要把我拍死了呀!!!微笑

文章中带有LPSTUDY的字样表明是我个人的理解,可能会有不对的地方,敬请指教。

文章原文链接地址:

[html]  view plain copy
  1. http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW1


不要使用dealloc管理稀缺资源

 

你不应该使用dealloc方法去管理像文件描述符,网络连接以及缓存之类的稀缺资源。特别是,你不应该去设计类想当然的认为dealloc将会在你认为的地方触发。dealloc的触发可能由于bug或者程序的崩溃被延迟或者规避掉。

 

相反,如果你有一个类的实例管理稀缺资源,那么你应该设计你的程序去告诉实例变量在适当的时候去清理资源,然后再去调用dealloc来释放实例变量。如果dealloc没有被调用,你就不会遭受比较严重的问题。

 

当你在dealloc方法中去管理资源时,问题可能就会出现。例如:

1.    对象图销毁的顺利依赖

对象图销毁机制内在是没有顺利,虽然你可能期望有一个特定的顺序,但通常这是不可靠的。如果一个对象不合适宜的落入了自动释放池中,对象的销毁顺序可能会改变,这会导致意想不到的问题

2.    没有回收稀缺资源

内存泄露的问题需要被解决,但是它们通常并不立刻引发致命的问题。如果一个稀缺资源没有在你想让它释放的时候释放掉,那么你可能遇到严重的问题。例如当你的程序用光了文件描述符,用户就不能保存数据了。

3.    清理逻辑在错误的线程中被执行

如果一个对象在一个错误的时间被放入了自动释放池中,它可能会被释放掉而不会管它碰巧是在哪一个线程池中。这可能是致命的,因为这个对象本改只被另一个线程访问。

 

LPSTUDY:

            说实话,这一段读起来有一点拗口,太理论化了。我的理解是:当你管理稀缺资源的时候,不要在dealloc中做。比如你想在dealloc去释放文件描述符,但是可能由于程序的bug原因,dealloc没有被执行,也就是说这个文件描述符没有被释放。如果这个dealloc需要被执行多次,也就有很多你想释放的文件描述符没有被释放掉。这样很明显是错误的。当然上面说的有三种dealloc引起的问题,我仅仅是举了第二种例子。总的来说:不要用dealloc管理稀缺资源,换句话说,不要太相信dealloc的执行。

 

收集类拥有(retain)它们包含的对象

当你向一个收集类(例如数组,词典或者集合)添加了一个元素,那么这个收集类就拥有了这个元素。当你调用收集类的remove方法,或者此收集类自身被释放的时候,这个收集类释放元素的所有权。因此,如果你想创建一个数组,你可以采用以下方式:

NSMutableArray *array = <#Get a mutable array#>;

NSUInteger i;

// ...

for (i = 0; i < 10; i++) {

    NSNumber *convenienceNumber = [NSNumber numberWithInteger:i];

    [array addObject:convenienceNumber];

}

上面的这种情况没有调用alloc,因此也没有必要调用release。你也不需要调用retain方法,因为array已经做了。

 

NSMutableArray *array = <#Get a mutable array#>;

NSUInteger i;

// ...

for (i = 0; i < 10; i++) {

    NSNumber *allocedNumber = [[NSNumber alloc] initWithInteger: i];

    [array addObject:allocedNumber];

    [allocedNumber release];

}

上面的这种你调用了alloc方法,故而在addobject之后,你需要调用release方法。在addobject中,array已经对allocedNumber调用了retain操作。

 

如果你想更好的理解上面的机制,那么请你站在收集类设计者的角度上来看待它。因为你想确保你的收集类不依赖于外部传入进来的元素是否在以后的某一个时刻被释放了,于是你在元素传入进来的时候调用了retain操作。如果它们被移除了,你为了平衡添加的时候的retain,于是调用了release操作。在收集类的dealloc方法中,你应该对所有剩下的元素调用release方法。

 

拥有策略是通过引用计数实现的。

拥有机制通过引用计数实现,每一个对象有一个引用计数

·     当你创建了一个对象,它的引用计数是1

·     当你对此对象发送retain消息,它的引用计数增1

·     当你发送release消息,引用计数减1

当你发送autorelease消息,它的引用计数会在未来的某一个时候减1

·     如果一个对象的引用计数为0,它会被释放掉

 

重要:

            你不应该去显式的观测对象的引用计数值,它的结果可能不正确,这主要是因为系统的框架可能会在你不知情的情况下调用了retain操作。在调试内存管理问题的时候,你应该总是去确保你的代码严格遵守了对象的拥有规则。

你可能感兴趣的:(iphone(object-c) 内存管理(3) 有效的内存管理 后半部分)