作者yllan (蓝永伦)
看板MacDev
标题Re: [quiz] NSImage's leak
时间Wed Nov 28 14:35:18 2007
※ 引述《anpig (Andrew)》之铭言:
: 不好意思把旧文搬出来讨论。
: 最近又重新K了一次cocoa memory management
: 就想到你在这边贴的文章
: 刚刚重看完详解之後有个疑问,就是你说在loop里放autorelease pool
: 看来用意是要release在loop里allocate NSImage时
: 所附带产生出需要autorelease的物件
: 是否是因为这些物件在产生NSImage物件过程中用了[xxx autorelease];
: 但是非得等到loop这个scope结束才会clean up,而且会clean up的原因
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
到这句话为止是正确的!
: 不是retain count为0,而是因为成为garbage。以上的理解正确吗?
这边不正确。Objective-C 1.0 并没有 garbage collection,只要有东西
变成 garbage (已经没有指标指向它) 就没救了,再也收不回来。
autorelease 没那麽神奇/复杂,他只是一个简单漂亮的实作:
当遇到 [xxx autorelease] 的时候,并不减少 xxx 的 retainCount,
而是让「最靠近」的 NSAutoreleasePool 去记录 xxx 收了多少次 auto-
release,等到那个 NSAutoreleasePool 本身 dealloc 的时候,就对所有
记录下来的物件送「刚刚记录下来那麽多次」 release。
所以这个时候,retainCount 也是会变成 0 的。
也就是说,[xxx autorelease] 可以想成「延迟 release」。
延迟到什麽时候?延迟到「最靠近的 NSAutoreleasePool」deallocated 的
时候。
: 所以这样说来,在[img release];时候把这些附带产生的物件的retain count
: 减至1,还需要一个autorelease pool来将他们的retain count减至0
: 是这样吗?
ㄟ?你这边又说对了...
我猜猜看,可能是我题目只写了部份程式码造成你误解了?
我题目好像这样写:
int i;
for (i = 0; i < 1000; i++) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSImage *img = [[NSImage alloc] initWithContentsOfFile:@”xxx.jpg”];
[img release];
[pool release];
}
你是不是以为这个直接包在 main() 里面,四周都没有 NSAutoreleasePool 呢?
如果是这样那就是我题目没有说明清楚,非常抱歉了...
在一般由 NSApplicationMain setup 起来的 Cocoa 程式里,Main Run Loop
会帮你自动 create/destroy NSAutoreleasePool,所以只要你的 method
结束,跳回 Main Run Loop 的话,之前的 autoreleased object 就会被清掉。
我的题目是建设在这个假设之上,也就是说在该段程式码所属函式跑完以後,
里面的 autorelease object 还是会 release 的,不会成为 garbage,只是
我想强调「因为 delay 到结束才 release,累积的东西太多造成效能低落」。
那如果是自己写 main(), 例如写纯文字工具的时候,或者是在新的 Thread
开头和结尾通常都要是 NSAutorelease 的 create/destory.
int main() {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
// ...[your code]...
[pool release];
return 0;
}
否则程式会出问题,因为 Cocoa Framework 里面物件的使用是假设在任何
用到这些物件的时刻都有至少一个 NSAutoreleasePool,没有的话会发生错误。
至於为什麽 NSImage 的生成会用到 autoreleased object 呢?我後来体会
到,这是一个保险的做法。在平行且多绪的环境下,若是没有处理好 retain/
release,程式很可能会 crash。像是最基本的 accessor, 都很多人这样写:
- (id) someMember {
return [[_someMember retain] autorelease];
}
其实 Objective-C 真的很简单,和 C 语言差不多,There's no magic.
他写什麽就做什麽,却能保持不错的弹性和效率。ObjC 2.0 开始引进了一些
magic 了,例如 GC 和 atomic accessor... 离题自删。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 59.112.163.47
1F:→ yllan:最近感觉 Cocoa 相关问题开始活络起来了,不知道和 11/28 14:39
2F:→ yllan:CocoaHeads Taipei Chapter 的设立有没有关系! 11/28 14:40