2013-07-20 178 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