NSAutoreleasePool EXC_BAD_ACCESS&关于Objective-C中的内存管理的问题

时间:2011-01-07 13:58:32

标签: iphone objective-c memory-management

我很难理解NSAutoReleasePool的工作原理。

1)NSAutoReleasePool是单独跟踪每个分配还是依赖于变量?换句话说,这会泄漏内存还是释放?:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
 NSArray* myObj = [NSObject alloc];  
 myObj = [NSObject alloc];  
 [pool release];

2)为什么以下代码有效:

 NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];

 NSArray* myObj = [NSObject alloc];

 for(int i = 0; i < 100; i++) {
  [myObj release];
  myObj = [NSObject alloc];
 }

 [pool1 release];

,但以下内容为[pool1 release]提供了EXC_BAD_ACCESS:

 NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];

 NSArray* myObj = [NSObject alloc];

 NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init]; 

 for(int i = 0; i < 100; i++) {
  [myObj release];
  myObj = [NSObject alloc];
 }

 [pool2 release];
 [pool1 release];

3)如何使上面的代码工作(带有2个池的代码)?

3 个答案:

答案 0 :(得分:5)

自动释放池仅适用于您自动发布的对象。代码中的所有对象都不会自动释放,因此没有任何对象会受​​到您创建的池的影响。

因此,答案是:

  1. 它泄漏了两个对象(因为它们都没有被释放或自动释放)
  2. 没有。它泄漏了最后一个分配的对象
  3. The documentation says that you can nest them。如果我假设您拥有[NSObject alloc],那么您的意思是[[[NSObject alloc] init] autorelease],那么您的第二个代码示例将会失败,因为您第一次发布myObj它将是在{{1}之外声明的对象}}。这意味着当您pool2 release时,它会尝试释放已释放的对象。让它工作的方法是不释放(或自动释放)一个对象多于保留或分配的对象。

答案 1 :(得分:2)

NSAutoreleasePool不跟踪分配。当您将消息autorelease发送到对象时,它会在其线程上搜索自动释放池(一个是通过运行循环在每次行程的顶部自动创建的,并在底部取消分配;在大多数其他例如,你需要手动创建它们)。如果找到一个,则将其添加到自动释放池维护的对象列表中。

当释放自动释放池时,它会将release消息发送到其列表中的每个项目。如果项目已多次添加到列表中,则会多次释放。

至于你的代码获得EXC_BAD_ACCESS的原因,我不确定。它可能与您未在任何NSObject上调用init这一事实有关,或者它可能与您尚未向我们展示的代码有关。

答案 2 :(得分:2)

一些事情:

:创建对象时始终使用init方法。 (即[[NSObject alloc] init])

:对象在自动释放时会添加到AutoreleasePool中。此示例中的对象只是被释放,因此根本不会使用自动释放池。你可以通过删除所有自动释放池来看到这一点;代码仍然运行良好。

:第一个例子会泄漏内存。您正在分配两个对象,但从不释放它们。如果你要自动发布它们,那么你可能会得到你正在寻找的行为并且不会有泄漏。

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray* myObj = [[[NSObject alloc] init] autorelease];
myObj = [[[NSObject alloc] init] autorelease];
[pool release];

:示例2工作,因为您只是分配,而不是释放对象;其中没有一个使用自动释放池。您可以删除自动释放代码以查看此内容。

:我无法复制您在示例3中看到的行为。也许您的代码中还有其他内容。