2011-01-07 82 views
1

我很难理解NSAutoReleasePool的工作原理。NSAutoreleasePool EXC_BAD_ACCESS&Objective Objective-C中有关内存管理的问题

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个池的代码)?

+1

请下次使用,请勿使用,而是使用``或单击面板上的符号{}。这是我们在这里所做的:D – vodkhang 2011-01-07 14:06:29

回答

5

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

因此,答案是:

  1. 它泄漏两个对象(因为没有被释放或自动释放)
  2. 没有。它泄漏分配的最后一个对象
  3. The documentation says that you can nest them。如果我假设你有[NSObject alloc]你真的意思是[[[NSObject alloc] init] autorelease],那么你的第二个代码示例将失败,因为你第一次发布myObj它将用于在pool2之外声明的对象。这意味着当你releasepool1它试图释放一个已经释放的对象。实现它的工作方式是不释放(或自动释放)一个对象的次数超过其保留或分配的次数。
2

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

当自动释放池被释放时,它将release消息发送到其列表中的每个项目。如果一个项目被多次添加到列表中,它将被多次释放。至于为什么你的代码得到一个EXC_BAD_ACCESS,我不确定。这可能与你没有在你的任何NSObject上调用init的事实有关,也可能与你尚未向我们显示的代码有关。

2

有几件事情:

:当创建对象总是使用init方法的。 (即[[NSObject alloc] init])

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

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

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

:示例2的工作原理,因为您只是分配,而不是释放对象;没有一个正在使用autorelease池。您可以删除autorelease代码来查看。

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