2013-07-20 80 views
1

我有一個類複製的NSString和打印它的保留計數和地址。@property複製和手動內存管理與自動釋放池

@interface TestStringPointer : NSObject 

@property (copy) NSString *stringTest; 

- (void)printPointer; 

@end 

@implementation TestStringPointer 

- (void)printPointer { 
    NSLog(@"PrintPointer:%p\n RetainCount:%lu", _stringTest, [_stringTest retainCount]); 
} 

@end 

在我的主要功能中,我對字符串的指針進行了一些調查,並遇到了一個問題。

int main(int argc, const char * argv[]) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    TestStringPointer *test = [[TestStringPointer alloc] init]; 

    NSString *myString = [NSString stringWithUTF8String:"Hello World"]; 
    NSLog(@"MyString: %p \n RetainCount:%lu", myString, [myString retainCount]); 

    [test setStringTest:myString]; 
    [test printPointer]; 
    [myString release]; 
    [pool drain]; 

    while (1) { 
    [test printPointer]; 
    } 

    return 0; 
} 

當我調試應用程序時,它通過while循環第3次崩潰(通過循環次數變化)。我明白,複製不會導致字符串不可變。 它在主要版本發佈後,我預計它會回到1.
1)如果一個對象沒有自動發佈,它是否仍然影響autorelease池?
2)不會有一個最大保留計數,防止池中的對象被耗盡,或者是否將其標記爲刪除?
3)拷貝是否應該在某一時刻進入,並在拷貝被刪除之前做了拷貝?

StringPointerTest [2253:303]的MyString:0x100100f60 RetainCount:1
StringPointerTest [2253:303] PrintPointer:0x100100f60 RetainCount:2
StringPointerTest [2253:303] PrintPointer:0x100100f60 RetainCount:1152921504606846975
StringPointerTest [2253:303] PrintPointer:0x100100f60 RetainCount:1152921504606846975

如果我修改主要和刪除池

int main(int argc, const char * argv[]) 
{ 

    TestStringPointer *test = [[TestStringPointer alloc] init]; 

    NSString *myString = [NSString stringWithUTF8String:"Hello World"]; 
    NSLog(@"MyString: %p \n RetainCount:%lu", myString, [myString retainCount]); 

    [test setStringTest:myString]; 
    [test printPointer]; 
    [myString release]; 

    while (1) { 
    [test printPointer]; 
    } 

    return 0; 
} 

所有是右...永遠...

StringPointerTest [423:303]的MyString:0x10010a670 RetainCount:1
StringPointerTest [423:303] PrintPointer:0x10010a670 RetainCount:2
StringPointerTest [423:303] PrintPointer:0x10010a670 RetainCount:1
...

回答

0

的錯誤是,當你鬆開myString。這是錯誤的,因爲stringWithUTF8String返回一個自動釋放字符串(請記住,每個方法都有自動釋放版本:靜態方法,而非自動釋放版本:init或initWithSomething:)。所以當autorelease池被耗盡後,myString保留計數變爲零,並且對象被解除分配(也許以後,你不知道什麼時候,它在第三次循環迭代中崩潰的事實是隨便的)。

因此,您通過撥打alloc + initWithUTF8String:而不是stringWithUTF8String:來解決問題。事實上,你看到一個令人難以置信的高保留數只是因爲內存已經被釋放並且可能再次寫入,在對象被真正釋放之前,這只是一個陷阱,你不再擁有這個對象。

+0

保留計數較高的原因是因爲該對象可以通過他調用的任何API函數保留和自動釋放任意次數。保留數通常是無用的。 – newacct