我正在学习Objective-C。我试图释放我使用的所有内存。所以,我写了一个程序来测试我是否做得对:
#import <Foundation/Foundation.h>
#define DEFAULT_NAME @"Unknown"
@interface Person : NSObject
{
NSString *name;
}
@property (copy) NSString * name;
@end
@implementation Person
@synthesize name;
- (void) dealloc {
[name release];
[super dealloc];
}
- (id) init {
if (self = [super init]) {
name = DEFAULT_NAME;
}
return self;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Person *person = [[Person alloc] init];
NSString *str;
int i;
for (i = 0; i < 1e9; i++) {
str = [NSString stringWithCString: "Name" encoding: NSUTF8StringEncoding];
person.name = str;
[str release];
}
[person release];
[pool drain];
return 0;
}
我正在使用带雪豹的mac。要测试它使用了多少内存,我会在它运行的同时打开Activity Monitor。几秒钟后,它正在使用千兆字节的内存。我该怎么办才能使它不那么用?
答案 0 :(得分:5)
首先,你的循环不正确。 +stringWithCString:…
不是+alloc
/ +new…
/ -copy
方法,因此您不应-release
。
其中任何一个都是正确的:
请勿-release
:
str = [NSString stringWithCString: "Name" encoding: NSUTF8StringEncoding];
person.name = str;
使用-init
:
str = [[NSString alloc] initWithCString: "Name" encoding: NSUTF8StringEncoding];
person.name = str;
[str release];
同样,在-[Person init]
:
- (id) init {
if ((self = [super init])) {
name = [DEFAULT_NAME copy]; // <----
}
return self;
}
现在,如果你使用变量#1,内存应该像你以前看到的那样上升到千兆字节,而变体#2应该是一个相当恒定的小值。
不同之处在于
str = [NSString stringWithCString: "Name" encoding: NSUTF8StringEncoding];
相当于
str = [[[NSString alloc] initWithCString:......] autorelease];
-autorelease
d对象意味着“将所有权转移到最近的NSAutoreleasePool,然后让它在以后发布”。
多晚了?默认情况下,当前运行循环勾选一次。但是,这里没有明确的运行循环*,因此运行循环没有运行。自动释放池永远不会有机会清除这10个 9 分配的临时字符串。
但是,对于变体#2,临时字符串会立即释放,因此临时字符串不会填满内存。 (我们不需要等待池刷新 - 没有涉及池。)
注意:
*:run loop是附加到每个正在运行的线程的唯一循环。如果编写CLI实用程序,则很少需要运行循环。