2011-07-25 58 views
2

在我的最後一個問題(here)後釋放三分球,我有我在那裏得到一個EXC_BAD_ACCESS因爲我在釋放我剛剛分配的變量的一個問題:澄清關於何時分配

NSMutableArray* s = [[NSMutableArray alloc] init]; 
stack = s; 
[s release]; 

應該是

NSMutableArray* s = [[NSMutableArray alloc] init]; 
stack = s; 

但是,堆棧是我的班級的保留屬性。它宣稱,像這樣:

@interface StateStack() 
@property (nonatomic, retain) NSMutableArray* stack; 
@end 

我的印象是,當你分配一個「保留」變量,它會自動遞增對象的retainCount下。所以你應該開始釋放你的指針(如here)。

這兩種情況爲什麼不同?謝謝!

+0

[不同之間self.myIvar和myIvar?](http://stackoverflow.com/questions/3755108/different-between-self-myivar-and-myivar) –

+0

[mmalc的回答](http:///stackoverflow.com/questions/156243/object-allocate-and-init-in-objective-c/167783#167783)對你鏈接的問題也回答你的問題。 –

回答

3

沒有這種東西作爲「保留變量」。這是一個保留財產 - 意味着財產背後的設置方法保留了新的價值,並釋放舊的價值。但分配給一個變量只是分配。實際上,人們通常推薦直接分配給init中的實例變量的原因是,它不會通過setter,因爲setter可能會產生你不想在init中產生的副作用(當你的對象不是'尚未完全構建)。

注:我在這裏談論正常的內存管理規則。如果你使用ARC,這是完全不同的。但我想你會提到,如果你是。

+0

感謝您直接在init中分配實例變量的提示,我不知道 – ario

6

因爲您必須分配屬性,而不是實例變量。當你分配給屬性時,它會再次保留變量,然後你就不會遇到問題。下面是你的代碼應該是:

NSMutableArray* s = [[NSMutableArray alloc] init]; 
self.stack = s; 
[s release]; 

這樣,你不分配給變量,而是使用屬性(這是,事實上,一個方法)。如果你在這種情況下沒有發佈,那麼你的代碼中會有內存泄漏。

當你做了stack = s你直接分配給實例變量,並且數組從未被保留。

3

self.stackstack是兩個完全不同的東西。當您使用stack時,您正在訪問實例變量,而不是屬性。這意味着您的訪問器方法未被調用,這意味着不使用自動內存管理。這就是爲什麼你不應該在你的例子中釋放s

如果您改用self.stack,那麼您將使用屬性。編譯器會將self.stack = value[self setStack:value]完全相同,self.stack[self stack]相同。由於正在使用訪問器,內存管理將按照您定義屬性的方式進行處理,並且應在分配值後釋放值。

1

Maurício有正確的答案:一定要分配給屬性以獲得@property的好處。在一定程度上澄清這一點,請嘗試使用這樣的代碼:

@interface StateStack : NSObject { 
    NSArray *_stack; 
} 
@property (nonatomic,retain) NSMutableArray *stack; 
@end 

@implementation StateStack 
@synthesize stack=_stack; 
@end 

現在,如果你嘗試:

NSMutableArray* s = [[NSMutableArray alloc] init]; 
stack = s; 
[s release]; 

你會得到一個錯誤,這將意味着你想設置的伊娃,而不是該財產如預期。伊娃姓名和房產名稱之間的這種不匹配違反了蘋果的建議,但是當您打算這樣做時,這是一種很好的方式來幫助您養成使用財產分配的習慣。