为什么这个程序占用了这么多内存?

时间:2010-06-05 18:10:59

标签: objective-c memory

我正在学习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。几秒钟后,它正在使用千兆字节的内存。我该怎么办才能使它不那么用?

1 个答案:

答案 0 :(得分:5)

首先,你的循环不正确。 +stringWithCString:…不是+alloc / +new… / -copy方法,因此您不应-release

其中任何一个都是正确的:

  1. 请勿-release

    str = [NSString stringWithCString: "Name" encoding: NSUTF8StringEncoding];
    person.name = str;
    
  2. 使用-init

    str = [[NSString alloc] initWithCString: "Name" encoding: NSUTF8StringEncoding];
    person.name = str;
    [str release];
    
  3. 同样,在-[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实用程序,则很少需要运行循环。