2011-01-07 47 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中看到的行爲。也許您的代碼中還有其他內容正在執行。